都能表示字符串对象,区别在于双引号字W串能够支持更多的{义字W。下面的代码在字W串中增加了'W号?br />
str=‘he'lo’
puts str
昄l果为he'lo?br />
单引号仅支持\\ => \ ?\' => '
下表是ruby中双引号字符串支持的转义字符Q?/p>
所有不是字母或者数字的单字节字W都可以成ؓString的分界符。注意,通常他们都是成对出现的,比如<?gt;,!?,{和}{?/p>
Ҏ一Q?br />
最单的使用单引h者双引号括v来的字符Ԍ比如"hello"?br />
Ҏ二:
使用%q配合分界W,%q代表单引?br />
str=%q!he\lo!
Ҏ三:
使用%Q配合分界W,%Q代表双引?br />
str=%Q{he\lo}
Ҏ四:
here document构徏字符Ԍ该方法比较适合用于多行字符串的创徏。由<<和边界字W串作ؓ开_p界字W串作ؓl尾Q比如下列代码:
str = <<END_OF_STRING1
We are here now,
where are you?
END_OF_STRING1
puts str
输出l果为:
We are here now,
where are you?
较ؓ复杂的是允许多个边界字符串对出现?br />
str = <<END_OF_STRING1,<<END_OF_STRING2
We are here now,
where are you?
END_OF_STRING1
I will leave now,
would you like to go with me?
END_OF_STRING2
puts str
输出l果为:
We are here now,
where are you?
I will leave now,
would you like to go with me?
在Java中,如果两个String对象a和b的值都?abcdef",如下Q?br />
String a="abcdef";
String b="abcdef";
?
么,JVM只会创徏一个常量对?abcdef",让a和b都指向它。但是在ruby中,采用了智能指针(熟悉c++的朋友清楚)的一个高U技?
copy-on-writeQ一开始也是共享同一个字W常量,但是一旦之后某个对象(比如b对象)q行了修Ҏ作,?abcdef"生一个副本,b
的修Ҏ作在q个副本上进行?br />
更详l的讨论请参考http://developer.51cto.com/art/200811/98630.htm?/p>
Java的String每次执行修改操作Q都不会改变自nQ而是创徏一个新的String对象Q而Ruby每次的修Ҏ作都会修改自w?/p>
puts "hello".length
该句输出5Q是字符个数Q不要和C函数搞QC函数l常?l束字符Ԍ因此长度l常为实际字W个?1QRuby中没有这个习惯?/p>
indexҎ有三U重载,分别是:
str.index(substring [, offset]) => fixnum or nil
str.index(fixnum [, offset]) => fixnum or nil
str.index(regexp [, offset]) => fixnum or nil
W二个参数offset是可选参敎ͼ不用的话则从索引0的字W开始查找?br />
puts "hello".index("el") 输出? Q注意这里的'el'也可以。也可以只查一个字W比Q如puts "hello".index(101) 输出?Q这时候第一个参Cؓ'e'的二q制码?br />
也可以用正则表辑ּq行查找Q比如puts "hello".index(/[az]/) 输出为nilQ因?hello"不包含a或者z。[]是正则表辑ּ的运符Q代表里面的a和z有一个找到即可?br />
puts "hello".index(/lo/) q个没有[]W号Q因此是查找子字W串loQ结果ؓ3.
我个得尽量熟l用正则表辑ּ查找是最好的选择Q既可以完成单查找,也可以完成难度查找。不q需要付Z努力去学习?br />
下面q个例子puts "hello".index('o', -1) 证明了第二个参数可以敎ͼ虽然q没有什么意义,因ؓ功能和ؓ0{h?br />
如果查找不到Q返回nil?/p>
str.rindex(substring [, fixnum]) => fixnum or nil
str.rindex(fixnum [, fixnum]) => fixnum or nil
str.rindex(regexp [, fixnum]) => fixnum or nil
W一个参数和index相同Q第二个参数是可选,如果不用则默认ؓ字符串尾部。如果ؓ0呢?则从W一个字W开始向x找。如果ؓ负数呢?q时候很奇怪,?
然能查到。通过看C的实C码,发现当fixnum<0Ӟ会执行这个运:fixnum+=substring.lengthQ然后就能找到。?
辑上可以理解为当fixnum<0Ӟ从最双开始向左移动abs(fixnum)-1个位|,q作为最后查找范_然后开始从左至双行查找?
字符串最双的字W的位置?1代表?br />
下面两行代码l果都是nil:
puts "hlloe".rindex('e', -2)
puts "hlloe".rindex('e', 3)
下面两行代码l果都是1Q?br />
puts "hello".rindex('e', -2)
puts "hello".rindex('e', 3)
注意Q以上的代码理解是我个h观察代码后的猜测Q因为我q不会调试运行ruby的C代码Q所以不一定正。代码摘录如下:Q代码是ruby|站公布的C?
码,但是我所用的q_其实NetBeans6.7.1Q因此真正代码应该是Java实现的JRuby1.2.0Q这里的C代码仅供参考)
static VALUE
rb_str_rindex_m(argc, argv, str)
int argc;
VALUE *argv;
VALUE str;
{
VALUE sub;
VALUE position;
long pos;
if (rb_scan_args(argc, argv, "11", ⊂, &position) == 2) {
pos = NUM2LONG(position);
if (pos < 0) {
pos += RSTRING(str)->len;
if (pos < 0) {
if (TYPE(sub) == T_REGEXP) {
rb_backref_set(Qnil);
}
return Qnil;
}
}
if (pos > RSTRING(str)->len) pos = RSTRING(str)->len;
}
else {
pos = RSTRING(str)->len;
}
switch (TYPE(sub)) {
case T_REGEXP:
if (RREGEXP(sub)->len) {
pos = rb_reg_adjust_startpos(sub, str, pos, 1);
pos = rb_reg_search(sub, str, pos, 1);
}
if (pos >= 0) return LONG2NUM(pos);
break;
case T_STRING:
pos = rb_str_rindex(str, sub, pos);
if (pos >= 0) return LONG2NUM(pos);
break;
case T_FIXNUM:
{
int c = FIX2INT(sub);
unsigned char *p = (unsigned char*)RSTRING(str)->ptr + pos;
unsigned char *pbeg = (unsigned char*)RSTRING(str)->ptr;
if (pos == RSTRING(str)->len) {
if (pos == 0) return Qnil;
--p;
}
while (pbeg <= p) {
if (*p == c) return LONG2NUM((char*)p - RSTRING(str)->ptr);
p--;
}
return Qnil;
}
通常我们理解Z双开始查找,但是注释却表明是从左向右查找Qƈq回最后一个找到的目标的位|。究竟内q如何,只能看代码?br />
01161 static
long
01162
rb_str_rindex
(str, sub, pos)
01163 VALUE
str, sub;
01164 long
pos;
01165 {
01166 long
len = RSTRING
(sub)->len;
01167 char
*s, *sbeg, *t;
01168
01169 /* substring longer than string */
01170 if
(RSTRING
(str)->len < len) return
-1;
01171 if
(RSTRING
(str)->len - pos < len) {
01172 pos = RSTRING
(str)->len - len;
01173 }
01174 sbeg = RSTRING
(str)->ptr;
01175 s = RSTRING
(str)->ptr + pos;
01176 t = RSTRING
(sub)->ptr;
01177 if
(len) {
01178 while
(sbeg <= s) {
01179
if
(
rb_memcmp
(s, t, len) == 0) {
01180
return
s -
RSTRING
(str)->ptr;
01181 }
01182 s--;
01183 }
01184 return
-1;
01185 }
01186 else
{
01187 return
pos;
01188 }
01189 }
通过看代码,发现s--;因此Q是从右向左q行匚wQ找到的W一个就q回。写注释的h应该枪毙!虽然看上L思一P但是法的时间复杂度大不一栗从左到右的查找LO(n),而从叛_左的最坏事件复杂度才是O(n)?br />
puts "hello".upcase.index("H")Q利用downcase或者upcase全部转换成小写或者大写,然后再查找?/p>
operator =~ 返回匹配的模式开始位|,如果没有扑ֈ则返回nil?br />
puts "abcde789" =~ /d/
输出5.
str="hello"
puts str[0,2]
W一个参数是子字W串首字母的IndexQ第二个是长度(不能敎ͼ?br />
l果为he?br />
W一个参数可以ؓ负数Q会把最双的字W作?1Q然后向左增?1的方式查找v始位|,比如Q?br />
str="hello"
puts str[-2,2]
输出为loQ这U情冉|们在rindexҎ中已l看到过了?br />
也可以用正则表辑ּq行提取Q这真的很强大?br />
str="hello"
puts str[/h..l/]
输出为hell?br />
W号.代表一个字W,两个.代表两个字符。两?里面的内容就是正则表辑ּ?*代表可以有无C字符Q比?br />
str="hello"
puts str[/h.*o/]
输出为hello?/p>
String#count用来计算我们参数中给出的字符集中字符出现的L敎ͼ比如最单的情况Q?br />
str = "hello,world"
puts str.count "w"
“w" 参数代表的是一个字W结合,里面只有一个字WwQcountҎ计算出w出现?hello,world"的次数是1Q因此输Zؓ1?br />
下面我们的参数里面包含了三个字符Q?br />
str = "hello,world"
puts str.count "wld"
输出?Qw出现1ơ,l出现3ơ,d出现1ơ,正好5ơ?br />
也可以传递多个参敎ͼ每个参数代表一个字W集合,q时候这些字W集合的交集作ؓcount计算的条Ӟ
str = "hello,world"
puts str.count "lo","o"
输出??br />
str = "hello,world"
puts str.count "lo","o"," "
输出?Q因Z个集合的交集为空Q所以计结果ؓ0.
注意Q如果参数^o,代表o出现的次C计算?/p>
String#chompҎ有一个字W串参数Q指定了要在末尾删除的子字符丌Ӏ如果不用这个参敎ͼ则会字W串末尾的n,r和rn删除Q如果有的话Q?/p>
String#squeezeҎ如果不用参数Q则会将字符串中的Q何连l重复字W变成单一字符Q如下:
str = "helllloo"
puts str.squeeze
输出Qhelo?br />
如果传递字W串参数Q含义同countҎ的参CP代表了一个字W集合,则将W合条gQ?Q在字符集合中出玎ͼ2Q在字符串中q箋出现Q的子字W串压羃成的单一字符
实例代码如下Q?br />
str = "helllloo"
puts str.squeeze('l')
puts str.squeeze('a-l')
puts str.squeeze('lo')
输出为:
heloo
heloo
helo
参数也可以用a-z方式表示在某个字W集合区间内?br />
一个很常用的功能是利用squeeze(" ")对字W串内重复的I白字符q行压羃?/p>
可以接收多个参数Q每个参C表一个字W集合,cMcountҎ。如果有多个参数Q取交集Q然后从字符串中删除所有出现在交集中的字符?br />
"hello".delete "l","lo" #=> "heo"
"hello".delete "lo" #=> "he"
"hello".delete "aeiou", "^e" #=> "hell"
"hello".delete "ej-m" #=> "ho"
参见后面的sub用法Q?'q行替换卛_?br />
String#split接收两个参数Q第一个参数L被作为间隔符来拆分字W串Qƈ且不会出现在l果中?br />
W一个参数如果是正则表达式的话,如果为空Q则每个字符都被拆开Q返回一个字W数l。例子代码如下:
str = "hello"
puts str.split(//)
输出为:
h
e
l
l
o
如果正则表达式不为空Q则Ҏ匚w的情况进行拆分。例子代码如下:
str = "hello"
puts str.split(/h/)
l果为:
ello
拆分成了两个数组Q第一个ؓ""Q第二个为elloQ用hq行拆分的?br />
W一个参数的另一U用法很单,只是一个字W串Q用于作为间隔符q行拆分Q就不D例子了。我更們于用强大的正则表达式?br />
W二个参数是一个整敎ͼ用于Ҏ分的l果数组的元素个数进行限Ӟq个功能有多大用处,我现在到没有体会Q一般情况下不用卛_?/p>
如前面出现的Q利用downcase或者upcaseҎ卛_?/p>
使用[]Q里面填上IndexQ就可以获取WIndex个元素?/p>
获取单字节字W的二进制码
puts ?e
Q运符用于中文是非法的?/p>
Rubyq代器的设计不在q里讨论Q我会专门有一文章描q?/p>
q代每个字符Q下面是CZ代码Q?br />
require 'jcode' #NetBeans6.7.1和JRuby1.2.0需要,否则下面代码找不到方?br />
"hello".each_char(){ |c| print c,' ' } #()可以不写
|c| 代表字符串中的当前字W?/p>
q代每个子字W串Q如果不传递seperator参数Q则默认用n作ؓseperator?br />
"hellonworld".each { |c| puts c }
输出为:
hello
world
如果传递了有效的字W串作ؓseperator参数Q那么就以这个seperator代替nq行子字W串的P代:
"hellonworld".each('l') { |s| p s }
输出为:
"hel"
"l"
"onworl"
"d"
用法和each_charcMQ不qP代的对象是charQ因此输出的是二q制数倹{?br />
"hellonworld".each_byte { |s| print s," " }
输出Q?br />
104 101 108 108 111 10 119 111 114 108 100
用法和前面相同,只是用换行符分割子字W串q行q代Q?br />
"hellonworld".each_line do |s|
print s
end
注意Q这是另一U写法,用do/end替换了{/}寏V?br />
输出为:
hello
world
只所以输Zؓ两行Q是因ؓW一个子字符串是"hellon"输出后自动换行?/p>
str1="hello,"
str2="world"
str3=str1+str2
puts str3
输出为hello,world
str1="hello,"
str2="world"
str1<
puts str1
输出为hello,world
concatҎ可以在字W串后面加上一个二q制gؓ[0,255]的字W,用法如下Q?br />
str1="hello,world"
str1.concat(33)#33?的二q制?br />
puts str1
输出为hello,world!
concat也可以接一个objectQ比如另一个String对象
String#empty? Ҏ 如果为空q回trueQ否则返回false
str1<=>str2
如果str1于str2Q返?1Q?br />
如果str1{于str2Q返?Q?br />
如果str1大于str2Q返??br />
官方注释写反了?/p>
两个比较对象必须都ؓStringQ否则返回false;
如果都是String对象Q则调用operator <=> 操作W进行比较,比较l果?Ӟq回trueQ否则返回false
和operator = 功能相同Q字W串内容的完全替换,没什么作用?br />
str.sub(pattern, replacement) => new_str
str.sub(pattern) {|match| block } => new_str
在str副本上将扑ֈ的第一个匹配字W(Ԍ用replacement替换Qƈq回。比如:
puts "abcde789".sub(/d/, "000")
输出为:abcde00089
W二U重载Ş式允许执行一D代码,比如Q?br />
puts "abcde789".sub(/d/){|c| 'a'}
扑ֈ的字W用|c|表示Q可以替换成a字符
输出为:abcdea89