Ruby字符串(1):String基本用法
String字符串
字符串由String类提供,除了直接使用单双引号或其它字面量创建字符串,也可以使用String.new()方法来创建。
a = "hello"
b = String.new("world")
Ruby中的字符串是可变对象。
字符串的连接
直接连接即可:
>> "a""b"
=> "ab"
>> "a" "b"
=> "ab"
>> "a" "b"
=> "ab"
单双引号
这和Perl一样,和Shell也类似。单引号是强引用,双引号是弱引用。
双引号的一个特性是支持表达式、变量内插,使用#符号即可。在Ruby中,#
前缀可以看作是一种对某对象的引用、调用之义。例如:
- 内插全局变量
#$var
- 内插实例变量
#@var
- 内插类变量
#@@var
- 但是对于普通的不带前缀符号的局部变量或表达式,为了避免歧义,通常在
#
后加上{}
。例如#{name}
、#{3+4}
、#{func("hello")}
所以,在双引号中如果#
字符后面的是$ @ @@ {
,需要对#
转义,其它时候,不需要对它转义。
格式化字符串内插
Ruby显然也是支持printf、sprintf的,但是Ruby除了表达式或变量内插,还支持格式化字符串内插。
sprintf "pi is about %.4f",Math::PI
=> "pi is about 3.1416"
"pi is about %.4f" % Math::PI # 单个格式化字符串
=> "pi is about 3.1416"
"%s: %f" % ["pi", Math::PI] # 多个格式化字符串
=> "pi: 3.141593"
"xiaomage = %{age}" % {:age => "23"}
=> "xiaomage = 23"
正如上面的示例,需要进行格式化的字符使用%
标识,并使用%
连接字符串和待替换的值。如果要内插多个字符串,则值部分使用中括号包围(即放进数组)或放进hash。
%q和%Q和%
这和Perl里的q() qq()
是一样的,也是分别充当单引号、双引号的角色。%q()
被解析成单引号,单个%
或%Q
被解析成双引号。
%q %Q
后面的()
是引号的起始、终止定界符,定界符可以替换成其他成对或相同的符号。例如,下面是等价的:
# 以下等价,内部的单引号不需要反斜线转义
%q(hello'world)
%q[hello'world]
%q{hello'world}
%q!hello'world!
%q#hello'world#
# 以下等价
%Q(hello'world)
%Q[hello'world]
%{hello'world} # 单个%是一样的
%!hello'world!
%#hello'world#
如果使用的是成对的定界符,那么在定界符内只要合理的配对,就可以包含定界符字面符号。例如:
%Q(hello(hello world)world)
%<<book>Ruby</book>>
%((1+(2*3)) = #{(1+(2*3))})
%(A mismatched paren \( must be escaped) # 不配对的括号需要转义
关于字符串的可变性
对于Ruby来说,字符串是可变的。所以,无法使用单个对象来引用内容相同的两个字符串,如果能引用的话,其中一个修改了就表示另一个字符串也会修改,但这已经表示同一个对象了。
所以,只要Ruby遇到一个字符串,都会新创建一个字符串对象。这意味着,如果在一个循环中使用了字符串常量,那么这个常量字符串对象也会在每次循环过程中新创建,而这是可以避免的消耗性能的一种方式。
>> 10.times {puts "test".object_id}
12046480
12046340
12046280
12046220
12046160
12046080
12046000
12045880
12045780
12045680
单字符
使用一个问号作为下一个字符的前缀,这个字符将称为字符字面量。例如:
?A # 代表一个大写字母A
?? # 代表一个问号
?" # 代表一个双引号
在Ruby1.8及之前的版本,这是一个单字符序列,会转换成ASCII码存放,在Ruby 1.9之后,单字符等价于只有一个字符的字符串。
>> ?A == 'A'
=> true
扩展字符串:+ * <<
想要连接两个字符串,直接不使用任何连接符或使用"+"就可以。但注意,它们不会自动将其它类型转换成字符串类型,需要手动调用to_s方法来转换。
>> "A""B"
=> "AB"
>> "A"+"B"
=> "AB"
>> "A"2 # SyntaxError:
>> "A"+2 # TypeError
>> "A"+2.to_s
=> "A2"
可使用"<<"将多个字符串追加到某个字符串的尾部,它同样不会自动转换成字符串。这时候字符串就像是一个字符数组一样,但需要知道,Ruby字符串不是字符数组,只是实现了一些好用的操作字符串的方法:
>> "abc" << "hello" <<"world"
=> "abchelloworld"
<<
可以直接追加整数,整数被当作ASCII或其它编码字符进行转换,使得追加到字符串里的是字符。
>> "xyz" << 65
=> "xyzA"
只是需要注意的是,使用+
或直接相连扩展字符串的方式时会自动创建一个新的字符串对象,原始字符串不变,也就是说在得到扩展的结果前拷贝了一些数据进行创建新字符串对象。而使用<<
的方式,因为修改的是字符数组,所以是原地修改的。
>> a="xyz"
=> "xyz"
>> a + "XYZ"
=> "xyzXYZ"
>> a # a没有变
=> "xyz"
>> a << "XYZ"
=> "xyzXYZ"
>> a # a已经变了
=> "xyzXYZ"
*
号重复字符串N次。于是,可以简单地写出等长的万恶分割线。例如:
>> "ab" * 3
=> "ababab"
>> '-' * 40
=> "----------------------------------------"
字符串的索引属性
字符串可变、可索引子串、设置子串、插入子串、删除子串等等。
字符串[]()搜索和赋值
通过[]
可以对字符串进行搜索和赋值,赋值时是原处修改字符串的。索引方式有多种,且支持负数索引号。
# 1.根据索引,搜索或赋值单元素
str[index] → new_str or nil
str[index] = new_str
# 2.根据索引和给定长度,搜索或赋值0或多个元素
str[start, length] → new_str or nil
str[start, length] = 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
与索引搜索、索引赋值(包括替换、插入、删除元素)、索引检查元素是否存在等操作有一些相对应的String方法。如下。
include?()
字符串中是否存在某子串。
include? other_str → true or false
"hello".include? "lo" #=> true
"hello".include? "ol" #=> false
"hello".include? ?h #=> true
index()
搜索某子串或匹配的子串的索引位置。
index(substr[, offset]) → int or nil
index(regexp[, offset]) → int or nil
例如:
"hello".index('e') #=> 1
"hello".index('lo') #=> 3
"hello".index('a') #=> nil
"hello".index(?e) #=> 1
"hello".index(/[aeiou]/, -3) #=> 4
replace()
替换字符串为另一个字符串,它会替换掉全部内容。它会原处修改字符串。
replace(other_str) → str
s = "hello" #=> "hello"
s.replace "world" #=> "world"
insert()
在字符串中某个位置处开始插入另一个字符串。它会原处修改字符串。
insert(index, other_str) → str
"abcd".insert(0, 'X') #=> "Xabcd"
"abcd".insert(3, 'X') #=> "abcXd"
"abcd".insert(4, 'X') #=> "abcdX"
"abcd".insert(-3, 'X') #=> "abXcd"
"abcd".insert(-1, 'X') #=> "abcdX"
字符串的迭代
因为字符串支持索引操作,所以可以直接通过索引的方式进行迭代。
a="hello"
i=0
while(i<a.length) do
puts a[i]
i += 1
end
0.upto(a.size - 1 ) do |x|
print a[x]
end
可以将字符串split成数组,然后通过each迭代。注意,Ruby 1.9里字符串不能直接通过each迭代了,它不再max-in Enumerable中的each。
a="hello"
a.split("").each do |x|
puts x
end
Ruby的字符串类中还定义了4个迭代方式:each_byte、each_char、each_line、each_codepoint。最常用的,显然是each_char。
a = "hello"
a.each_char do |x|
puts x
end
each_byte、each_codepoint迭代时,得到的是各字符的ASCII码或Unicode代码点。
"我".each_byte.to_a #=> [230, 136, 145]
"我是单身狗".each_byte.to_a
#=> [230, 136, 145, 230, 152, 175, 229, 141,
# 149, 232, 186, 171, 231, 139, 151]
"我".each_codepoint.to_a #=> [25105]
"我是单身狗".each_codepoint.to_a
#=> [25105, 26159, 21333, 36523, 29399]
按块读取数据(或按段落读取)时,很可能会用上each_line来迭代缓冲中的一大段数据的每一行。
each_line(separator=$/ [, getline_args]) {|substr| block } → str
每迭代,都将该行传递到代码块中。
其中:
separator
指定记录(行)分隔符,默认的是\n
、\r
或\r\n
。
getline_args
指定读取到每一行时的所作的操作,目前支持的是:chomp
选项,表示将每行尾部的换行符移除掉。这是非常方便的功能,这样在迭代每一行的时候,不需要手动在代码块中使用chomp()了。
str="a line\nb line\nc line\n"
str.each_line {|x| puts "#{x}"}
# 输出:
=begin
a line
b line
c line
=end
下面是使用chomp
参数的功能。
str="a line\nb line\nc line\n"
str.each_line(chomp: true) {|x| puts "#{x}: #{x.length}"}
# 输出:
=begin
a line: 6
b line: 6
c line: 6
=end
# 等价于
str.each_line {|x| x.chomp!();puts "#{x}: #{x.length}" }
# 输出:
=begin
a line: 6
b line: 6
c line: 6
=end
下面是指定行分隔符的用法。
str="a line\nb line\nc line\n"
str.each_line("e") {|x| puts "-#{x}-"}
# 输出:
=begin
-a line-
-
b line-
-
c line-
-
-
=end
# 指定分隔符和chomp参数的时候
str.each_line("e", chomp:true) {|x| puts "-#{x}-"}
-a lin-
-
b lin-
-
c lin-
-
-
字符串的比较
Ruby中典型的几种方法:<=>、eql?、equal?、==、===
。当然,因为实现了<=>
,所以也送了< > <= >= between?
这几个比较方法。
其中,对于纯字符串对象,==、===、eql?
等价,都用于判断字符串内容是否相同。==
是判断对象的内容是否完全一致(或者说是相等);===
是智能判断,对于字符串而言,等价于==
;eql?
是根据计算对象hash值进行比较的,对于字符串的hash()方法来说,它是根据字符串长度、内容、编码三个属性来生成hash值的。
equal?
则最严格,只有双方引用的是同一对象时,才返回true。
说明下eql?
比较。下面是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
此外,String类还实现了casecmp
和casecmp?
。前者是无视大小写的<=>
,后者是无视大小写的等值比较。编码不同或一方不是字符串时,返回nil。
casecmp(other_str) → -1, 0, +1, or nil
casecmp?(other_str) → true, false, or 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
Ruby中字符串内存问题
Ruby字符串(1):String基本用法的更多相关文章
- go中字符串类型string的用法
示例 // 字符串类型string的用法 package main import ( "fmt" "unsafe" ) func main() { // 字符串 ...
- 雷林鹏分享:Ruby 字符串(String)
Ruby 字符串(String) Ruby 中的 String 对象存储并操作一个或多个字节的任意序列,通常表示那些代表人类语言的字符. 最简单的字符串是括在单引号(单引号字符)内.在引号标记内的文本 ...
- Swift - 字符串(String)用法详解
下面对String常用的属性和方法做个总结 1,判断是否为空:isEmpty 1 2 3 var str:String if str.isEmpty{ } 2,获取字符数量:countElements ...
- lua字符串处理(string库用法)
原文地址http://www.freecls.com/a/2712/f lua的string库是用来处理字符串的,基础函数如下 string.byte(s [, i [, j]]) string.by ...
- ruby 字符串常用方法学习
引用链接:http://www.blogjava.net/nkjava/archive/2010/01/03/308088.html 1,切片:silce, [ ]-----------------[ ...
- C#中string.format用法详解
C#中string.format用法详解 本文实例总结了C#中string.format用法.分享给大家供大家参考.具体分析如下: String.Format 方法的几种定义: String.Form ...
- Ruby字符串
在Ruby中的String对象持有和操纵的任意序列的一个或多个字节,通常表示人类语言的字符表示.简单的字符串文本括在单引号中,如 'This is a simple Ruby string liter ...
- JavaScript中常见的字符串操作函数及用法
JavaScript中常见的字符串操作函数及用法 最近几次参加前端实习生招聘的笔试,发现很多笔试题都会考到字符串的处理,比方说去哪儿网笔试题.淘宝的笔试题等.如果你经常参加笔试或者也是一个过来人,相信 ...
- String.format()用法
package junit.test; import java.util.Date; import java.util.Locale; import org.junit.Test; pub ...
随机推荐
- 机器学习 vs. 深度学习
1. bias/vairance Trend # 1:Scale driving Deep Learning process. 2. feature learning 的方式 A common com ...
- mysql重置root密码,并设置可远程访问
linux系统: mysqld_safe --skip-grant-tables & mysql -u root use mysql UPDATE user SET host = '%' wh ...
- QT实现鼠标钩子(使用SetWindowsHookEx安装mouseProc函数)
HHOOK mouseHook=NULL; LRESULT CALLBACK mouseProc(int nCode,WPARAM wParam,LPARAM lParam ) { if(nCode ...
- sql 从未连续的Id中选择10~30条数据
select * from(select *,row_number()over(order by ProductID) as num from Products) as t where t.num&g ...
- js div的显示和隐藏
<head> <title></title> <style type="text/css"> div ...
- Delphi 10.2可以开发Linux桌面应用了
原始地址 https://community.embarcadero.com/blogs/entry/firemonkey-on-linux Delphi Linux编译器已经发布,现在无需等待 ...
- aspx页面@Page指令解析
@Page指令位于每个ASP.NET页面的顶部,告诉ASP.NET这个具体页面使用什么属性,以及该页面继承的用户控件.ASP.NET页面@Page指令属性有:AspCompat.Async.Async ...
- API Hook基本原理和实现
API Hook基本原理和实现 2009-03-14 20:09 windows系统下的编程,消息message的传递是贯穿其始终的.这个消息我们可以简单理解为一个有特定意义的整数,正如我们看过的老故 ...
- WPF 的DynamicResource的NewLine问题
wpf的TextBlock支持换行,换行可以用 符号来表示. 比如: <TextBlock Text="第1行 第2行"></TextBlock> 显示效果 ...
- 搭建svn服务器&服务器客户端使用笔记
参考借鉴文章:http://www.cnblogs.com/vijayfly/p/5711962.html 之前尝试着用git管理公司代码,但被一个问题困惑了很久无法解决,那就是git该如何只pull ...