骏马金龙

网名骏马金龙,钟情于IT世界里的各种原理和实现机制,强迫症重症患者。爱研究、爱翻译、爱分享。特借此一亩三分田记录自己成长点滴!!!
我本问道人,道心不坚,必将与道无缘!

Ruby字符串(2):String方法详细整理

String方法整理

官方手册

类方法

new

new(str="") → new_str
new(str="", encoding: enc) → new_str
new(str="", capacity: size) → new_str

encoding指定创建什么编码的字符串,即new_str是什么编码的。

capacity指定创建字符串对象时预先分配好的buffer大小。如果以后要扩容该字符串,就不需要再临时动态分配内存。对于后续可能需要频繁扩展该字符串的情况,可以提升一些性能。

例如:

try_convert

try_convert(obj) → string or nil

尝试通过调用to_s()将obj转换成字符串,如果不能转换,则不报错而是返回nil。

String.try_convert("hello")  #=> "hello"
String.try_convert(/re/)     #=> nil

实例方法

%格式化字符串

str % arg → new_str

arg有三种方式:单参数、数组、hash

"%05d" % 123                          #=> "00123"
"%-3s: %05d" % [ "ID", 123 ]          #=> "ID : 00123"
"foo = %{foo}" % { :foo => 'bar' }    #=> "foo = bar"

除了%,还有sprintf()(Kernel模块中)也可以格式化字符串。

*重复字符串

str * integer → new_str

integer必须是大于等于0的整数,表示重复str字符串N次。重复0次表示返回空字符串。

"Ho! " * 3   #=> "Ho! Ho! Ho! "
"Ho! " * 0   #=> ""

+串联扩展字符串

str + other_str → new_str

将other_str串联追加到str的尾部。注意,返回的是新字符串对象,而不是原处修改的

a="hello"

a + self.to_s  #=> "hellomain"

puts a         #=> "hello"

<<和concat和prepend原处追加字符串

str << obj → str
str << integer → str
concat(obj1, obj2, ...) → str
prepend(other_str1, other_str2, ...) → str

将给定obj对象追加到str的尾部,很经常的,obj会是另一个字符串对象,表示将另一个字符串追加到str尾部进行扩展。注意是原处修改的

如果追加的是一个integer,则integer被当作是代码点(或ASCII码),于是将对应的字符插入到str的尾部。

如果obj不能转换成字符串(通过to_str方法而不是to_s方法),则报错,例如Array对象有to_s但是没有to_str方法,所以Array不能追加到str尾部。

<<可以多个串联在一起,例如a <<"hello" <<"world"

concat功能和<<一样,它可以接收多个参数。它也是原处修改对象

a = "hello "
a << "world"   #=> "hello world"
a << 33        #=> "hello world!"

b = "hello
b << "xyz" <<"hello"
b              #=> "helloxyzhello"

a="hello"
a.concat("world","nihao")  #=>helloworldnihao

prepend()是将一个或多个其它字符串插入到字符串的前端。它也是原处修改对象。

a = "!"
a.prepend("hello ", "world") #=> "hello world!"
a                            #=> "hello world!"

+-可变和不可变(frozen)字符串

+str → str (mutable)
-str → str (frozen)
freeze()

+str表示返回一个可变的字符串对象:

  • 如果原始字符串是frozen的,则拷贝一份并返回它的可变对象
  • 如果原始字符串本身就是可变的(字符串默认就是可变的),则返回自身,不拷贝字符串对象

-str表示返回一个不可变(frozen)的字符串对象:

  • 如果原始字符串是可变的,则拷贝一份
  • 如果原始字符串本身不可变,则返回自身

freeze()也表示返回不可变字符串对象,它都是在原处修改的。

所以,[+ -]str可能会创建新对象,而freeze则总是使得原始字符串不可变。

>> a="world"     #=> "world"
>> a.object_id   #=> 15976580

>> b = +a        #=> "world"
>> b.object_id   #=> 15976580  # 因为a本身可变,所以不拷贝,返回自身

>> a="world"     #=> "world"
>> a.object_id   #=> 8911880

>> b=-a          #=> "world"
>> b.object_id   #=> 8897840   # 因为a可变,所以拷贝,返回新的不可变对象b
>> b[1]="OO"     # b不可变,RuntimeError: can't modify frozen String

>> a[1]="OO"     # a仍然可变
=> "OO"
>> a
=> "wOOrld"

>> b.object_id   #=> 8854280
>> c = -b        #=> "world"    # b不可变,所以-b返回自身
>> c.object_id   #=> 8854280

>> d = +b        #=> "world"    # b不可变,所以+b创建新对象
>> d.object_id   #=> 11837980

>> x="hello"     #=> "hello"
>> x.object_id   #=> 11676080

>> y=x.freeze    #=> "hello"  # x和y是同一对象,都不可变
>> y.object_id   #=> 11676080
?> x[1]="E"      # RuntimeError: can't modify frozen String
>> y[1]="E"      # RuntimeError: can't modify frozen String

比较字符串

string <=> other_string → -1, 0, +1, or nil
str == obj → true or false
str != obj → true or false
str === obj → true or false
eql?(other) → true or false
equal? → true or false

比较字符串大小:

  • 左边小于右边,则返回-1
  • 左边等于右边,则返回0
  • 左边大于右边,则返回1
  • 两者不可比较(比如一方不是字符串),则返回nil

有了<=>之后,就默认有了<、<=、> 、>=between?方法。

对于字符串而言,=====eql?是等价的,都用于比较字符串是否相同,String遵守了Ruby对equal?的设计要求:不要轻易去重写equal?,所以String直接从BasicObject中继承了equal?,它比较的是两者是否是同一对象。

"abcdef" <=> "abcde"     #=> 1
"abcdef" <=> "abcdef"    #=> 0
"abcdef" <=> "abcdefg"   #=> -1
"abcdef" <=> "ABCDEF"    #=> 1
"abcdef" <=> 1           #=> nil

"abc" == "abc"      #=> true
"abc" === "abc"     #=> true
"abc".eql? "abc"    #=> true
"abc".equal? "abc"  #=> false

to_f、to_i、to_r

to_s、to_str

to_sym

# str向数值类转换
to_f → float
to_i(base=10) → int
to_r → rational

# str向字符串转换
to_s → str
to_str → str

# str向symbol转换
to_sym → symbol

to_f表示将字符串转换成浮点数,从头部开始转换,尾部无效字符会忽略。无法转换时返回0.0

"123.45e1".to_f        #=> 1234.5
"45.67 degrees".to_f   #=> 45.67
"thx1138".to_f         #=> 0.0

to_i表示将字符串转换成整型数,从头部开始转换,尾部无效字符会忽略。无法转换时返回0。可以指定base=N参数来控制如何解析字符串,例如指定base=16时,那么就能识别字符串的a字符。

"12345".to_i             #=> 12345
"99 red balloons".to_i   #=> 99
"0a".to_i                #=> 0
"0a".to_i(16)            #=> 10
"hello".to_i             #=> 0
"1100101".to_i(2)        #=> 101
"1100101".to_i(8)        #=> 294977
"1100101".to_i(10)       #=> 1100101
"1100101".to_i(16)       #=> 17826049

to_r表示将字符串转换成分数形式。忽略前缀空白以及后缀无效字符。

'  2  '.to_r       #=> (2/1)
'300/2'.to_r       #=> (150/1)
'-9.2'.to_r        #=> (-46/5)
'-9.2e2'.to_r      #=> (-920/1)
'1_234_567'.to_r   #=> (1234567/1)
'21 June 09'.to_r  #=> (21/1)
'21/06/09'.to_r    #=> (7/2)
'BWV 1079'.to_r    #=> (0/1)

注意,"0.3".to_r0.3.to_r是不同的,后者是浮点数转换为分数,而浮点数是不精确的,比如这里假设0.3等于0.30000000000009,那么0.3.to_r等价于"0.30000000000009".to_r

关于to_sym,等价于intern,参见intern

=~正则匹配字符串

str =~ obj → integer or nil
  • 如果obj是一个正则表达式,则用此正则去匹配str,匹配成功则返回匹配到的第一个字符的位置,否则返回nil
  • 如果obj不是正则表达式,则调用obj.=~(str),即调用obj的=~方法,然后以str作为参数

注:str =~ reg 和 reg =~ str是不同的,如果reg里有命名捕获,则只有第二种才会将捕获到的内容赋值到对应的变量当中。所以在Ruby中,强烈建议将reg放在前面,这和Perl的位置顺序是相反的

>> "hello" =~ /(?<x>e)/  #=> 1
>> x  # NameError: undefined local variable or method `x' for main:Object

>> /(?<x>e)/ =~ "hello"  #=> 1
>> x                     #=> "e"

索引、搜索和赋值

slice和slice!

字符串可变、可索引子串、设置子串、插入子串、删除子串等等。

通过[]可以对字符串进行搜索和赋值,赋值时是原处修改字符串的。索引方式有多种,且支持负数索引号。

此外,slice()slice!()分别等价于str[]搜索和str[] = xxx赋值。

# 1.根据索引,搜索或赋值单元素
str[index] → new_str or nil
str[index] = new_str

# 2.根据索引和给定长度,搜索或赋值0或多个元素
str[start, length] → new_str or nil
str[index, integer] = new_str

# 3.根据索引范围,搜索或赋值0或多个元素
str[range] → new_str or nil
str[range] = aString

# 4.根据正则模式(斜线包围正则表达式),搜索或赋值匹配到的元素
str[regexp] → new_str or nil
str[regexp] = new_str

# 5.根据正则模式(包含分组匹配),返回给定分组内容
# capture可以是分组名,也可以是分组索引号(即反向引用)
# 分组索引号为0表示regexp匹配的所有内容
# 如果是赋值操作,则替换给定分组的内容
str[regexp, capture] → new_str or nil
str[regexp, integer] = new_str
str[regexp, name] = new_str

# 6.根据给定字符串精确搜索或赋值
str[match_str] → new_str or nil
str[other_str] = new_str

可以说,Ruby对字符串的索引操作支持的是相当的丰富、完善。下面是一些例子:

a = "hello there"

a[1]                   #=> "e"
a[2, 3]                #=> "llo"
a[2..3]                #=> "ll"

a[-3, 2]               #=> "er"
a[7..-2]               #=> "her"
a[-4..-2]              #=> "her"
a[-2..-4]              #=> ""

a[11, 0]               #=> ""
a[11]                  #=> nil
a[12, 0]               #=> nil
a[12..-1]              #=> nil

a[/[aeiou](.)\1/]      #=> "ell"
a[/[aeiou](.)\1/, 0]   #=> "ell" 等价于上面方式
a[/[aeiou](.)\1/, 1]   #=> "l"   第一个分组内容
a[/[aeiou](.)\1/, 2]   #=> nil   第二个分组

a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "non_vowel"] #=> "l"
a[/(?<vowel>[aeiou])(?<non_vowel>[^aeiou])/, "vowel"]     #=> "e"

a["lo"]                #=> "lo"
a["bye"]               #=> nil

s = "hello"
while(s["l"])     # 将所有的l替换成L
    s["l"] = "L"
end

ascii_only?

ascii_only? → true or false

如果字符串中只包含ASCII字符,则返回true。

b

b → str

返回字符串的一个ASCII-8BIT编码的拷贝。

bytes

bytes → an_array

返回字符串各字符的字节数组。等价于a.each_byte.to_a

>> a=%q(hello)  #=> "hello"
>> a.bytes      #=> [104, 101, 108, 108, 111]
>> a.each_byte.to_a  #=> [104, 101, 108, 108, 111]

chars

chars → an_array

返回字符串各字符的数组。等价于a.each_char.to_a

a="hello"
a.chars          #=> ["h", "e", "l", "l", "o"]
a.each_char.to_a #=> ["h", "e", "l", "l", "o"]

lines

lines(separator=$/ [, getline_args]) → an_array

返回字符串中各行组成的数组。sep指定行分隔符(记录分隔符),getline_args支持的选项目前只有:chomp。等价于a.each_line.to_a

"hello\nworld\n".lines              #=> ["hello\n", "world\n"]
"hello world".lines(' ')            #=> ["hello ", "world"]
"hello  world".lines(' ')           #=> ["hello ", " ", "world"]
"hello\nworld\n".lines(chomp: true) #=> ["hello", "world"]

"hello\nworld\n".each_line.to_a     #=> ["hello\n", "world\n"]

codepoints

返回字符串各代码点的数组。等价于a.each_codepoint.to_a

"我是单身狗".codepoints  
    #=> [25105, 26159, 21333, 36523, 29399]

"我是单身狗".each_codepoint.to_a
    #=> [25105, 26159, 21333, 36523, 29399]

bytesize

bytesize → integer

返回字符串的字节数量。

"\x80\u3042".bytesize  #=> 4
"hello".bytesize       #=> 5
"我".bytesize          #=> 3

注:是字节长度不是字符数量。返回字符数量的是length()或size()。

size和length

length → integer
size → integer

返回字符串的字符数量。

"hello".size       #=> 5
"我".size          #=> 1

byteslice

byteslice(int) → new_str or nil
byteslice(int, len) → new_str or nil
byteslice(range) → new_str or nil

按字节截取字符串。字节索引可以为负数表示从尾部开始计算位置。

如果初始范围超出边界或len为负数,则返回nil。

"hello".byteslice(1)     #=> "e"
"hello".byteslice(-1)    #=> "o"
"hello".byteslice(1, 2)  #=> "el"
"\x80\u3042".byteslice(1, 3) #=> "\u3042"
"\x03\u3042\xff".byteslice(1..3) #=> "\u3042"

capitalize和capitalize!

capitalize → new_str
capitalize([options]) → new_str

capitalize! → str or nil
capitalize!([options]) → str or nil

将字符串首字母转换成大写字母,剩余的转换成小写字母。

对于capitalize!,如果没有做任何转换操作,则返回nil。

关于options选项,主要和编码有关,参见downcase

"hello".capitalize    #=> "Hello"
"HELLO".capitalize    #=> "Hello"
"123ABC".capitalize   #=> "123abc"

a = "hello"
a.capitalize!   #=> "Hello"
a               #=> "Hello"
a.capitalize!   #=> nil

downcase和downcase!

downcase → new_str
downcase([options]) → new_str

downcase! → str or nil
downcase!([options]) → str or nil

将字符串转换成小写字母。

对于downcase!,如果没有做任何转换操作,则返回nil。

关于options选项,主要和编码有关,参见downcase

"hEllO".downcase   #=> "hello"

upcase和upcase!

upcase → new_str
upcase([options]) → new_str

upcase! → str or nil
upcase!([options]) → str or nil

将字符串转换成大写字母。

对于upcase!,如果没有做任何转换操作,则返回nil。

关于options选项,主要和编码有关,参见downcase

>> "hello".upcase  #=> "HELLO"

swapcase和swapcase!

swapcase → new_str
swapcase([options]) → new_str

swapcase! → str or nil
swapcase!([options]) → str or nil

大小写互换:大写转小写、小写转大写。对于swapcase!,如果没有进行转换操作,则返回nil。

"Hello".swapcase          #=> "hELLO"
"cYbEr_PuNk11".swapcase   #=> "CyBeR_pUnK11"

casecmp和casecmp?

casecmp(other_str) → -1, 0, +1, or nil
casecmp?(other_str) → true, false, or nil

casecmp实现了大小写无关的<=>操作。如果编码不同或一方不是字符串,则返回nil。

casecmp?考虑编码,将字符串解码后进行等值比较。相等则返回true,不等则返回false,如果编码不同或一方不是字符串,则返回nil。

"1234abc".casecmp("1234ABC")  #=> 0

"我".casecmp("我") #=> 0

"\u{c4 d6 dc}" #=> "ÄÖÜ"
"\u{e4 f6 fc}" #=> "äöü"

"\u{c4 d6 dc}".casecmp("\u{e4 f6 fc}")  #=> -1
"\u{c4 d6 dc}".casecmp?("\u{e4 f6 fc}") #=> true

center

center(width, padstr=' ') → new_str

将字符串居中,左右两边填充padstr(默认为空格)。如果字符串的字符数量大于width,则返回拷贝后的相等字符串。

"hello".center(4)         #=> "hello"
"hello".center(20)        #=> "       hello        "
"hello".center(20, '123') #=> "1231231hello12312312"

chomp和chomp!

chomp(separator=$/) → new_str
chomp!(separator=$/) → str or nil

移除字符串尾部的单个换行符(严格地说是$/指定的记录分隔符),包括\n\r\r\n。但注意,尾部如果是\n\r,则只移除\r而留下\n

如果指定了separator,则移除尾部的这些字符串。

如果separator指定为空字符串,则移除尾部所有连续的换行符。

如果尾部没有换行符,即不需要移除。对于chomp,直接拷贝字符串并返回新对象,对于chomp!则返回nil。

"hello".chomp                #=> "hello"
"hello\n".chomp              #=> "hello"
"hello\r\n".chomp            #=> "hello"
"hello\n\r".chomp            #=> "hello\n"
"hello\r".chomp              #=> "hello"
"hello \n there".chomp       #=> "hello \n there"
"hello".chomp("llo")         #=> "he"
"hello\r\n\r\n".chomp('')    #=> "hello"
"hello\r\n\r\r\n".chomp('')  #=> "hello\r\n\r"

chop和chop!

chop → new_str
chop! → str or nil

移除字符串的最后一个字符。

如果字符串是空字符串,则chop直接返回一个空字符串,而chop!返回nil。

"string\r\n".chop   #=> "string"
"string\n\r".chop   #=> "string\n"
"string\n".chop     #=> "string"
"string".chop       #=> "strin"
"x".chop.chop       #=> ""

chr返回首字符

chr → string

返回字符串的首字符。

a = "abcde"
a.chr    #=> "a"

"我是单身狗".chr  #=> "我"

clear

clear → string

清空字符串。注意是原地修改的。

a = "abcde"
a.clear    #=> ""
a          #=> ""

count

count([other_str]+) → integer

从字符串中搜索给定字符的数量。多个other_str参数的交集确定要搜索的字符。支持^取反语义以及-取范围。如果要搜索这两个特殊字符本身,使用反斜线转义。

a = "hello world"
a.count "lo"                   #=> 5
a.count "lo", "o"              #=> 2,2个o
a.count "lo", "l"              #=> 3,3个l
a.count "hello", "^l"          #=> 4,heo共四个
a.count "ej-m"                 #=> 4,el共四个

"hello^world".count "\\^aeiou" #=> 4,^eo共4个
"he-llo-wor-ld".count "a\\-eo" #=> 6,-eo共6个

c = "hello world\\r\\n"
c.count "\\"                   #=> 2
c.count "\\A"                  #=> 0
c.count "X-\\w"                #=> 3

delete和delete!

delete([other_str]+) → new_str
delete!([other_str]+) → str or nil

删除字符串中的某些字符,返回删除后的字符串。

对于delete!,如果没有字符要删除,则返回nil。

other_str的规则和countother_str规则一致。

"hello".delete "l","lo"        #=> "heo"
"hello".delete "lo"            #=> "he"
"hello".delete "aeiou", "^e"   #=> "hell"
"hello".delete "ej-m"          #=> "ho"

delete_prefix和delete_prefix!

delete_suffix和delete_suffix!

delete_prefix(prefix) → new_str
delete_prefix!(prefix) → self or nil

delete_suffix(suffix) → new_str
delete_suffix!(suffix) → self or nil

从字符串头部或者字符串尾部删除指定的前缀、后缀。

如果没有需要删除的内容,对于delete_xxx,返回内容相同的新对象,对于delete_xxx!,则返回nil。

迭代each_xxx

包括each_byte、each_char、each_codepoint、each_line。

参见:字符串的迭代

up_to

upto(other_str, exclusive=false) {|s| block } → str
upto(other_str, exclusive=false) → an_enumerator

看例子:

"a8".upto("b6") {|s| print s, ' ' }
    #=> a8 a9 b0 b1 b2 b3 b4 b5 b6

for s in "a8".."b6"
  print s, ' '
end
    #=> a8 a9 b0 b1 b2 b3 b4 b5 b6
"9".upto("11").to_a   #=> ["9", "10", "11"]
"25".upto("5").to_a   #=> []
"07".upto("11").to_a  #=> ["07", "08", "09", "10", "11"]

empty?

empty? → true or false

判断字符串是否为空字符串。

"hello".empty?   #=> false
" ".empty?       #=> false
"".empty?        #=> true

encoding

encoding → encoding

返回字符串所使用的编码对象(Encoding Object)。

从此也可以知道所使用的是哪个编码。

>> var = "hello world"
>> var.encoding         #=> #<Encoding:UTF-8>
>> var.encoding.to_s    #=> "UTF-8"

encode和encode!

(1) encode(encoding [, options] ) → str
(2) encode(dst_encoding, src_encoding [, options] ) → str
(3) encode([options]) → str
 
(4) encode!(encoding [, options] ) → str
(5) encode!(dst_encoding, src_encoding [, options] ) → str

第(1)种表示转换成指定编码的新字符串对象。

第(2)种表示从src_encoding转换成dst_encoding编码的字符串对象。

第(3)种表示拷贝一个新字符串对象,编码不变。

>> var = "hello world"
>> var_gbk = var.encode("gbk")  #=> "hello world"
>> var_gbk.encoding.to_s        #=> "GBK"

>> var_default = var_gbk.encode() #=> "hello world"
>> var_default.encoding.to_s    #=> "GBK"

options参见http://ruby-doc.org/core-2.6.2/String.html#method-i-encode

force_encoding

force_encoding(encoding) → str

强制将字符串的编码转换为指定编码。注意,是原处修改

>> var = "hello world"
>> var.encoding.to_s           #=> "UTF-8"
>> var.force_encoding("GBK")   #=> "hello world"
>> var.encoding.to_s           #=> "GBK"

valid_encoding?

valid_encoding? → true or false

判断编码转换的过程是否正确。换句话说,原本可能因为编码转换报错的语句,现在不报错,而是返回bool值。

"\xc2\xa1".force_encoding("UTF-8").valid_encoding?  #=> true
"\xc2".force_encoding("UTF-8").valid_encoding?      #=> false
"\x80".force_encoding("UTF-8").valid_encoding?      #=> false

start_with?和end_with?

start_with?([prefixes]+) → true or false
end_with?([suffixes]+) → true or false

如果字符串的前缀、后缀能匹配所给定的字符串或正则表达式,则返回true。

注意,只有start_with能使用正则表达式的方式来匹配前缀,end_with只能通过精确匹配的方式。

可以给多个前缀、后缀参数,表示任意一个满足条件即可。

例如:

# 精确匹配前缀、后缀
"hello".start_with?("hell")      #=> true
"hello".end_with?("ello")        #=> true

# 正则方式匹配前缀
"hello".start_with?(/H/i)        #=> true

# 多个前缀、后缀匹配
"hello".start_with?("heaven", "hell")     #=> true
"hello".start_with?("heaven", "paradise") #=> false
"hello".end_with?("heaven", "ello")     #=> true
"hello".end_with?("heaven", "paradise") #=> false

getbyte和setbyte

getbyte(index) → 0 .. 255
setbyte(index, integer) → integer

获取或设置字符串中某个字节的byte值(一个整数值)。

>> var="hello"
>> var.bytes        #=> [104, 101, 108, 108, 111]
>> var.getbyte(1)   #=> 101

>> "我".bytes       #=> [230, 136, 145]
>> "我".getbyte(1)  #=> 136

gsub和gsub!

gsub(pattern, replacement) → new_str
gsub(pattern, hash) → new_str
gsub(pattern) {|match| block } → new_str
gsub(pattern) → enumerator

gsub!(pattern, replacement) → str or nil
gsub!(pattern, hash) → str or nil
gsub!(pattern) {|match| block } → str or nil
gsub!(pattern) → an_enumerator

gsub用来做字符串替换。

pattern部分是正则表达式对象,但也可以是双引号包围的正则字符串,但不建议。所以,应该遵从使用/pattern/的方式作为pattern参数的格式。

replacement表示要替换被pattern所匹配的内容。在replacement中,可以使用反向引用\N、分组捕获的分组引用\k<NAME>。replacement部分可以是双引号包围的,也可以是单引号包围的字符串,如果是双引号包围的,那么其中的反斜线要多加一个前缀\转义。

使用hash参数时,表示pattern匹配的内容是hash中的某个key,那么将根据hash中的key来对应替换。

使用语句块时,将传递所匹配的内容到代码块中,这时会自动设置好$1, $2, $, $&, $'等变量。

对于gsub!,如果没有做任何替换,则返回nil。

"hello".gsub(/[aeiou]/, '*')                  #=> "h*ll*"
"hello".gsub(/([aeiou])/, '<\1>')             #=> "h<e>ll<o>"
"hello".gsub(/./) {|s| s.ord.to_s + ' '}      #=> "104 101 108 108 111 "
"hello".gsub(/(?<foo>[aeiou])/, '{\k<foo>}')  #=> "h{e}ll{o}"
'hello'.gsub(/[eo]/, 'e' => 3, 'o' => '*')    #=> "h3ll*"

sub

sub(pattern, replacement) → new_str
sub(pattern, hash) → new_str
sub(pattern) {|match| block } → new_str

sub!(pattern, replacement) → str or nil
sub!(pattern) {|match| block } → str or nil

类似于gsub,但只替换一次。

"hello".sub(/[aeiou]/, '*')                  #=> "h*llo"
"hello".sub(/([aeiou])/, '<\1>')             #=> "h<e>llo"
"hello".sub(/./) {|s| s.ord.to_s + ' ' }     #=> "104 ello"
"hello".sub(/(?<foo>[aeiou])/, '*\k<foo>*')  #=> "h*e*llo"
'Is SHELL your preferred shell?'.sub(/[[:upper:]]{2,}/, ENV)
    #=> "Is /bin/bash your preferred shell?"

hash

hash → integer

根据字符串的长度、内容、编码生成hash值。在使用eql?比较的时候,所采用的比较依据就是hash值。

>> "hello".hash
=> -1983722257626684531
>> "h".hash
=> 2851888847349797667

下面是eql?()只当不同编码时的比较过程。

>> "我".encode("utf-8").eql?( "我".encode("utf-16") )
=> false

>> "hello".encode("utf-8").eql?( "hello".encode("utf-16") )
=> false

>> "hello".encode("utf-8").eql?( "hello".encode("gbk") )
=> true

hex

hex → integer

将字符串以16进制的方式解析并转换成10进制数值。所以,它是16进制 -> 10进制

如果字符串中存在了16进制解析不了的字符(即超出了0-9a-zA-Z)的字符,则返回0。但注意,对于字符0,它从16进制转换成10进制也返回0。

字符串的前缀如果是0x0X,则解析时自动识别它,不认为是需要解析的字符串。

>> "9".hex     #=> 9
>> "a".hex     #=> 10
>> "e".hex     #=> 14
>> "f".hex     #=> 15
>> "10".hex    #=> 16

>> "0xa".hex   #=> 10
>> "0Xa".hex   #=> 10
>> "0XA".hex   #=> 10
>> "-0xa".hex  #=> -10
>> "-23".hex   #=> -35

>> "0".hex     #=> 0
>> "g".hex     #=> 0

oct

oct → integer

将字符串以8进制的方式解析并转换成10进制数值。所以,它是8进制 -> 10进制

如果以8进制(只能识别0-7)的方式解析字符串时出错,返回0。但注意,对于字符0,它从8进制转换成10进制也返回0。

字符串的前缀如果是0,则解析时自动识别它,不认为是需要解析的字符串。

"123".oct       #=> 83
"-377".oct      #=> -255
"bad".oct       #=> 0
"0377bad".oct   #=> 255

ord

ord → integer

返回字符串第一个字符的数值。

"a".ord         #=> 97
"hello".ord     #=> 104
"h".ord         #=> 104
"我".ord        #=> 25105

include?

include? other_str → true or false

判断字符串中是否包含某个字符或某个子串。

>> "hello".include?("ll")  #=> true
>> "hello".include?("L")   #=> false
>> "hello".include?("")    #=> true

index和rindex

index(substring [, offset]) → integer or nil
index(regexp [, offset]) → integer or nil

rindex(substring [, integer]) → integer or nil
rindex(regexp [, integer]) → integer or nil

返回给定子串或正则模式所匹配内容的(从左或从右)第一个匹配的位置。也就是搜索字符串中是否包含某子串(或正则模式),并返回它的索引位置。

如果没有匹配到内容,则返回nil。

如果给定了第二个参数offset,则表示从此offset处开始向后搜索。

"hello".index('e')             #=> 1
"hello".index('lo')            #=> 3
"hello".index('a')             #=> nil
"hello".index(?e)              #=> 1
"hello".index(/[aeiou]/, -3)   #=> 4

"hello".rindex('e')             #=> 1
"hello".rindex('l')             #=> 3
"hello".rindex('a')             #=> nil
"hello".rindex(?e)              #=> 1
"hello".rindex(/[aeiou]/, -2)   #=> 1

replace

replace(other_str) → str

将字符串替换为另一个给定的字符串。注意是替换全部内容,且是原处修改对象

>> a="hello"           #=> "hello"
>> a.replace("world")  #=> "world"
>> a                   #=> "world"

insert

insert(index, other_str) → str

将给定字符串other_str插入到字符串的指定索引位置处。可以指定负数索引。注意是原处修改对象

a="hello"          #=> "hello"
a.insert(0,"good") #=> "goodhello"
a                  #=> "goodhello"

"abcd".insert(3, 'X')    #=> "abcXd"
"abcd".insert(4, 'X')    #=> "abcdX"
"abcd".insert(-3, 'X')   #=> "abXcd"
"abcd".insert(-1, 'X')   #=> "abcdX"

inspect

inspect → string

返回完全规范的字符串。所有需要转义的字符都会加上反斜线和双引号包围。

str = "hello"
str[3] = "\b"
str.inspect       #=> "\"hel\\bo\""

str.bytes         #=> [104, 101, 108, 8, 111]
>> p str          #=> "hel\bo"
>> puts str       # 输出heo

intern

intern → symbol

等价于to_sym,表示将字符串转换成symbol,如果symbol不存在,则新创建symbol对象。

"Koala".intern         #=> :Koala
s = 'cat'.to_sym       #=> :cat
s == :cat              #=> true
s = '@cat'.to_sym      #=> :@cat
s == :@cat             #=> true
'cat and dog'.to_sym   #=> :"cat and dog"

ljust和rjust

ljust(length, padstr=' ') → new_str
rjust(length, padstr=' ') → new_str

在字符串右、左边填充字符使得填充后字符串达到length长度。如果没有指定padstr则使用空格填充。如果length小于当前字符串长度,则不填充仅拷贝一个新字符串对象。

"hello".ljust(4)            #=> "hello"
"hello".ljust(20)           #=> "hello               "
"hello".ljust(20, '1234')   #=> "hello123412341234123"

"hello".rjust(4)            #=> "hello"
"hello".rjust(20)           #=> "               hello"
"hello".rjust(20, '1234')   #=> "123412341234123hello"

lstrip和lstrip!

rstrip和rstrip!

strip和strip!

lstrip → new_str
lstrip! → self or nil
rstrip → new_str
rstrip! → self or nil
strip → new_str
strip! → self or nil

移除字符串前缀、后缀空白。对于Xstrip!,如果没有进行移除操作,则返回nil。

"  hello  ".lstrip   #=> "hello  "
"  hello  ".rstrip   #=> "  hello"
"    hello    ".strip   #=> "hello"

"hello".lstrip       #=> "hello"
"hello".rstrip       #=> "hello"
"hello".strip           #=> "hello"

"\tgoodbye\r\n".strip   #=> "goodbye"
"\x00\t\n\v\f\r ".strip #=> ""

"  hello  ".lstrip!  #=> "hello  "
"  hello  ".rstrip!  #=> "  hello"
"  hello  ".strip!  #=> "hello"
"hello  ".lstrip!    #=> nil
"  hello".rstrip!    #=> nil
"hello".lstrip!      #=> nil
"hello".rstrip!      #=> nil
"hello".strip!      #=> nil

match和match?

match(pattern) → matchdata or nil
match(pattern, pos) → matchdata or nil

match?(pattern) → true or false
match?(pattern, pos) → true or false

match()的pattern可以是正则对象,也可以是字符串,如果是字符串将转换成正则表达式对象。

然后用pattern去匹配字符串,将匹配的内容放进MatchData类中,这个类中是对所有匹配到内容的封装。

指定了pos后,表示从此位置处开始向后搜索。

如果match()后给了代码块,则将MatchData传递给代码块。

match?在匹配到内容时返回true,否则返回false。

'hello'.match('(.)\1')      #=> #<MatchData "ll" 1:"l">
'hello'.match('(.)\1')[0]   #=> "ll"
'hello'.match('(.)\1')[1]   #=> "l"
'hello'.match(/(.)\1/)[0]   #=> "ll"
'hello'.match(/(.)\1/, 3)   #=> nil
'hello'.match('xx')         #=> nil

'hello'.match('(.)\1') {|x| p x}  #=> #<MatchData "ll" 1:"l">

"Ruby".match?(/R.../)    #=> true
"Ruby".match?(/R.../, 1) #=> false
"Ruby".match?(/P.../)    #=> false
$&                       #=> nil

next和next!

succ和succ!

next → new_str
next! → str

succ → new_str
succ! → str

next和succ等价。

将字符串最右边的字母/数组(不是最右边的字符,因为最右边的字符可能不是字母、数值)转换成它的下一个位。例如最右边的字符8变成9,a变成b。

需要注意:

  1. 数值和字母的递增很容易理解。但如果完全没有字母、数值,则最右边的字符按照排序规则进行递增
  2. 如果发生了进位操作,则返回到左边进行递增。这是递归的,直到没有可进位的操作为止。在进位的时候,有可能会增加一个字符。看下面的示例
"abcd".succ        #=> "abce"      # 最后一个字母
"THX1138".succ     #=> "THX1139"   # 最后一个数值
"<<koala>>".succ   #=> "<<koalb>>" # 最后一个字母
">>>".succ         #=> ">>?"       # 没有数值、字母,递增最后一个字符
"1999zzz".succ     #=> "2000aaa"   # 先递增zzz为aaa,进位后递增1999为2000
"ZZZ9999".succ     #=> "AAAA0000"  # 先递增9999为0000,进位后递增ZZZ为AAAA
"***".succ         #=> "**+"       # 没有数值、字母,递增最后一个字符

partition和rpartition

partition(sep) → [head, sep, tail]
partition(regexp) → [head, match, tail]

rpartition(sep) → [head, sep, tail]
rpartition(regexp) → [head, match, tail]

从左或从右开始匹配字符串,并将第一次匹配之前的内容、第一次匹配的内容、第一次匹配之后的内容这三部分组成一个数组。

"hello".partition("l")         #=> ["he", "l", "lo"]
"hello".partition("x")         #=> ["hello", "", ""]
"hello".partition(/.l/)        #=> ["h", "el", "lo"]

"hello".rpartition("l")         #=> ["hel", "l", "o"]
"hello".rpartition("x")         #=> ["", "", "hello"]
"hello".rpartition(/.l/)        #=> ["he", "ll", "o"]

reverse和reverse!

reverse → new_str
reverse! → str

将字符串字符反转。

"hello".reverse   #=> "olleh"

scan

scan(pattern) → array
scan(pattern) {|match, ...| block } → str

按照正则表达式匹配字符串,从前向后每次匹配到的结果放进数组或传递到代码块。

如果没有使用分组捕获,则从前向后每次匹配到的内容都作为数组的元素或直接传递给代码块。

如果使用了分组捕获,则正则每次匹配的分组放进子数组中。

a = "cruel world"
a.scan(/\w+/)        #=> ["cruel", "world"]
a.scan(/.l/)         #=> ["el", "rl"]
a.scan(/.../)        #=> ["cru", "el ", "wor"]
a.scan(/(...)/)      #=> [["cru"], ["el "], ["wor"]]
a.scan(/(..)(..)/)   #=> [["cr", "ue"], ["l ", "wo"]]


a.scan(/\w+/) {|w| print "<<#{w}>> " }
   #=> <<cruel>> <<world>>
a.scan(/(.)(.)/) {|x,y| print y, x }
   #=> rceu lowlr

split

split(pattern=nil, [limit]) → an_array
split(pattern=nil, [limit]) {|sub| block } → str

将字符串切分成数组。

如果pattern部分是字符串,则这个字符串的内容作为切割字符串的分隔符。

如果pattern部分是单个空格,则切割时所有空白符号都被忽略,包括前缀或后缀空白,相当于是压缩了所有空格,然后分隔,且忽略前后缀空白。

如果没有给pattern,则采取变量$;的值作为分隔符,如果没有设置过$;,它默认等价于使用单个空格作为pattern。

如果pattern部分是空字符串(0长字符串),则对每个字符都进行分割。

如果pattern部分是正则表达式,则每次在匹配的时候进行分割。如果pattern中包含了分组捕获,则对应的匹配也会放进数组中。

如果要切割的字符串是空字符串,则返回空数组。

如果省略limit参数,则会抑制尾随空字段。如果limit是正数,则最多返回拆分子字符串的数量(捕获的组也将返回,但不会计算到极限)。如果limit为' 1 ',则返回整个字符串作为数组中的唯一条目。如果是负数,则不限制返回的字段的数量,并且不抑制尾随空字段。

If the limit parameter is omitted, trailing null fields are suppressed. If limit is a positive number, at most that number of split substrings will be returned (captured groups will be returned as well, but are not counted towards the limit). If limit is 1, the entire string is returned as the only entry in an array. If negative, there is no limit to the number of fields returned, and trailing null fields are not suppressed.

" now's  the time ".split       #=> ["now's", "the", "time"]
" now's  the time ".split(' ')  #=> ["now's", "the", "time"]
"   hello  \tworld   ".split(" ")   #=> ["hello", "world"]

" now's  the time".split(/ /)   #=> ["", "now's", "", "the", "time"]
"1, 2.34,56, 7".split(%r{,\s*}) #=> ["1", "2.34", "56", "7"]
"hello".split(//)               #=> ["h", "e", "l", "l", "o"]
"hello".split(//, 3)            #=> ["h", "e", "llo"]
"hi mom".split(%r{\s*})         #=> ["h", "i", "m", "o", "m"]

"mellow yellow".split("ello")   #=> ["m", "w y", "w"]
"1,2,,3,4,,".split(',')         #=> ["1", "2", "", "3", "4"]
"1,2,,3,4,,".split(',', 4)      #=> ["1", "2", "", "3,4,,"]
"1,2,,3,4,,".split(',', -4)     #=> ["1", "2", "", "3", "4", "", ""]

"1:2:3".split(/(:)()()/, 2)     #=> ["1", ":", "", "", "2:3"]

"".split(',', -1)               #=> []

squeeze和squeeze!

squeeze([other_str]*) → new_str
squeeze!([other_str]*) → str or nil

压缩字符串中连续相同的字符为单个字符。

如果不给任何参数,则压缩所有连续相同的字符。

如果给参数,则从一个或多个参数中取交集。

"yellow moon".squeeze                  #=> "yelow mon"
"  now   is  the".squeeze(" ")         #=> " now is the"
"putters shoot balls".squeeze("m-z")   #=> "puters shot balls"
"putters shoot balls".squeeze("m-z","o")
    #=> "putters shot balls"        # 只有o被压缩了

tr和tr!

tr(from_str, to_str) => new_str
tr!(from_str, to_str) → str or nil

表示将字符串中所有from_str中出现的字符替换为一一映射到to_str中的字符。

"hello".tr('el', 'ip')      #=> "hippo"

这里e映射为il映射为p,表示将hello中的所有e替换为i,l替换为p。

如果to_str比from_str短,则将to_str的最后一个字符填充到to_str的尾部以便达到和from_str相同的长度进行一一映射。

# 以下两条语句等价
"hello".tr('aeiou', '*')    #=> "h*ll*"
"hello".tr('aeiou', "*****")#=> "h*ll*"

# 以下两条语句等价
"hello".tr('aeiou', 'AA*')    #=> "hAll*"
"hello".tr('aeiou', 'AA***')  #=> "hAll*"

from_str和to_str都可以使用-表示范围,例如0-9a-d等。

在from_str中还可以使用^表示除了这些字符,其它都替换,即从字符串中取反。所替换的目标字符串为to_str的最后一个字符。

"hello".tr('a-y', 'b-z')    #=> "ifmmp"
"hello".tr('^aeiou', '*')   #=> "*e**o" 
    # 上面第二条表示hello中除了aeiou,其它字母即h和l都替换

"hello".tr('^aeiou', '123457') #=> "7e77o"

tr_s和tr_s!

tr_s(from_str, to_str) → new_str
tr_s!(from_str, to_str) → str or nil

在进行tr替换后,压缩替换部分连续相同的字符。注意,非替换部分的字符不计入考虑。

"hello".tr_s('l', 'r')     #=> "hero"
"hello".tr_s('el', '*')    #=> "h*o"
"hello".tr_s('el', 'hx')   #=> "hhxo"
posted @ 2019-05-04 15:02 骏马金龙 阅读(...) 评论(...) 编辑 收藏