1. Normal String Delimiter ( ' and " )
前面两篇已经接触了很多String的例子, 下面再举一个, 注意看单引号和双引号的区别 :
执行结果 :
s1 = 'Hello'
s2 = 'World'
s3 = '#{s1} #{s2}'
s4 = "#{s1} #{s2}"
puts(s3)
puts(s4)
执行结果 :
#{s1} #{s2}
Hello World
2. User Defined String Delimiter
当String中有单引号或双引号比较多时, 需要很多转义. 那么有没有更简洁的输入方法呢 :
执行结果 :
s1 = 'I\'m Digoal'
s2 = "This is a double quota\""
puts(s1)
puts(s2
执行结果 :
I'm Digoal
This is a double quota"
单引号 : 使用%q// , 非数字字母的符合替代/. (如%q{}, %q!!, 等)
双引号 :
使用%Q// , 非数字字母的符合替代/.
(如%Q{}, %Q!!, 等)
双引号 :
使用%// , 非数字字母的符合替代/.
(如%{}, %!!, 等)
执行结果 :
3. Backquotes (execute OS command)
s1 = 'I\'m Digoal'
s2 = "This is a double quota\""
s3 = %q/I'm Digoal/
s4 = %Q(This is a double quota")
s5 = %q{#{s3} #{s4}}
s6 = %Q{#{s3} #{s4}}
s7 = %*#{s3} #{s4}*
puts(s1)
puts(s2)
puts(s3)
puts(s4)
puts(s5)
puts(s6)
puts(s7)
执行结果 :
I'm Digoal
This is a double quota"
I'm Digoal
This is a double quota"
#{s3} #{s4}
I'm Digoal This is a double quota"
I'm Digoal This is a double quota"
3. Backquotes (execute OS command)
在Ruby中执行操作系统命令有点类似SHELL脚本, 用反引号.
输入 / 后, 执行结果 :
与前面的自定义String delimiter一样, 反引号可以用%x//来替代.
#!/opt/ruby/bin/ruby
print("Please enter dir name, then i can list it:")
dir = gets().chomp
ls = `ls -la #{dir}`
puts(ls)
输入 / 后, 执行结果 :
total 204
drwxr-xr-x 29 root root 4096 Feb 8 17:35 .
drwxr-xr-x 29 root root 4096 Feb 8 17:35 ..
-rw-r--r-- 1 root root 0 Dec 27 14:30 .autofsck
-rw-r--r-- 1 root root 0 Oct 21 11:05 .autorelabel
drwxr-xr-x 2 root root 4096 Feb 8 17:07 bin
drwxr-xr-x 3 root root 4096 Oct 21 10:49 boot
drwxr-xr-x 14 root root 4120 Dec 27 14:30 dev
drwxr-xr-x 97 root root 12288 Feb 25 04:02 etc
drwxr-xr-x 5 postgres postgres 4096 Dec 26 14:58 hds1
drwxr-xr-x 4 postgres postgres 4096 Dec 26 14:58 hds2
drwxr-xr-x 7 root root 4096 Feb 8 16:42 home
drwxr-xr-x 11 root root 4096 Oct 21 12:29 lib
drwxr-xr-x 9 root root 12288 Oct 21 12:28 lib64
drwx------ 2 root root 16384 Oct 21 18:44 lost+found
drwxr-xr-x 2 root root 4096 May 11 2011 media
drwxr-xr-x 2 root root 0 Dec 27 14:30 misc
drwxr-xr-x 2 root root 4096 May 11 2011 mnt
drwxr-xr-x 2 root root 0 Dec 27 14:30 net
drwxr-xr-x 11 root root 4096 Feb 15 10:00 opt
drwxr-xr-x 3 postgres postgres 4096 Oct 21 11:08 pgdata
drwx------ 14 pg92 pg92 4096 Feb 24 14:22 pgdata1919
drwxr-xr-x 3 pgxc pgxc 4096 Feb 8 17:35 pgxc_gtm
dr-xr-xr-x 223 root root 0 Dec 27 22:29 proc
drwxr-x--- 9 root root 4096 Feb 24 15:58 root
drwxr-xr-x 2 root root 12288 Oct 21 12:29 sbin
drwxr-xr-x 2 root root 4096 Oct 21 10:45 selinux
drwxr-xr-x 2 root root 4096 May 11 2011 srv
drwxr-xr-x 11 root root 0 Dec 27 22:29 sys
drwxrwxrwt 5 root root 4096 Feb 28 09:01 tmp
drwxr-xr-x 15 root root 4096 Oct 21 10:46 usr
drwxr-xr-x 24 root root 4096 Oct 21 16:40 var
与前面的自定义String delimiter一样, 反引号可以用%x//来替代.
#!/opt/ruby/bin/ruby
print("Please enter dir name, then i can list it:")
dir = gets().chomp
ls = %x/ls -la #{dir}/ # 或者使用%x{}等.
puts(ls)
4. String Concatenation
String的连接操作, 有些是会改变操作符左边的字符的, 有些不会改. 我们来看个例子 :
( <<, +, 空格 )
执行结果 :
s1 = "Hello"
s2 = s1 << " World" # << 方法将改变s1的值.
puts(s1)
puts(s2)
s3 = "Digoal"
s4 = s3 + " Zhou" # + 方法不会改变s3的值.
puts(s3)
puts(s4)
s5 = "Digoal" " Zhou" # 空格只能用于两个单引号和双引号包围的字符串的连接
#s7 = %Q{Digoal} %Q{ Zhou} #不允许, 异常
#s8 = 'Digoal' s3 #不允许, 异常
#s9 = s3 ' Zhou' #不允许, 异常
puts(s5)
执行结果 :
Hello World
Hello World
Digoal
Digoal Zhou
Digoal Zhou
另外还有一个需要注意的是, integer如果出现在这些连接方法的右边, 会显示什么 ?
<< 中, 0-255会字段转换成ASCII码对应的字符.
+ 则必须使用to_s方法转换成String. 否则报错. 并且输出的是数字本身. 当然在<<中如果使用to_s也是显示数字本身.
执行结果 :
s1 = "This " << "is" << " a string " << 36 # char 36 is '$'
s2 = "This " + "is" + " a string " + 36.to_s
s3 = "This " "is" " a string " + 36.to_s
puts("(s1):" << s1)
puts("(s2):" << s2)
puts("(s3):" << s3)
执行结果 :
(s1):This is a string $
(s2):This is a string 36
(s3):This is a string 36
5. Comma Used with String (return Array)
注意使用<<, + , 空格返回的都是什么类型呢 ?
执行结果 :
那么接下来看看使用逗号连接会返回什么类型 :
执行结果 :
s1 = "Hello " << "World"
s2 = "Digoal " + "Zhou"
s3 = "A" "DBA"
puts(s1.class)
puts(s2.class)
puts(s3.class)
执行结果 :
String
String
String
那么接下来看看使用逗号连接会返回什么类型 :
s1 = "Hello " , "World"
puts(s1.class)
执行结果 :
Array # 返回的是Array类型, 可不是String哦.
6. String Assignment
从上一个例子我们知道<<会修改左边字符串, 而+不会修改它左边的字符串.
那么看看还有哪些方法会修改左边字符串的值, (一般以!结尾的方法是会修改左边字符串的值的)
执行结果 :
给Fixnum和String的对象赋值。看看object_id会不会发送改变 :
执行结果 :
s = "hello world"
print( "1) s='#{s}' and s.object_id=#{s.object_id}\n" )
s = s + "!" # this creates a new string object
print( "2) s='#{s}' and s.object_id=#{s.object_id}\n" )
s = s.capitalize # this creates a new string object
print( "3) s='#{s}' and s.object_id=#{s.object_id}\n" )
s.capitalize! # but this modifies the original string object
print( "4) s='#{s}' and s.object_id=#{s.object_id}\n" )
s[1] = 'A' # this also modifies the original string object
print( "5) s='#{s}' and s.object_id=#{s.object_id}\n" )
s << ' Digoal' # this also modifies the original string object
print( "6) s='#{s}' and s.object_id=#{s.object_id}\n" )
执行结果 :
1) s='hello world' and s.object_id=15923760 # 给String的对象赋值(不管这个值是否与原来的值相等)会改变object_id
2) s='hello world!' and s.object_id=15923664
3) s='Hello world!' and s.object_id=15923592 # 以下几个操作之后, object_id都没有变化, 但是s的值已经被修改了.
4) s='Hello world!' and s.object_id=15923592
5) s='HAllo world!' and s.object_id=15923592
6) s='HAllo world! Digoal' and s.object_id=15923592
给Fixnum和String的对象赋值。看看object_id会不会发送改变 :
i1 = 10
s1 = "Digoal"
puts(i1.class)
puts(i1.object_id)
puts(s1.class)
puts(s1.object_id)
# 以变量的形式赋值给新的变量, 看看新变量的object_id, 等于前者的OBJECT_ID
i2 = i1
s2 = s1
puts(i2.object_id)
puts(s2.object_id)
# 使用相同的值赋值给新的变量, String新变量的object_id与前者不同. 但是Fixnum类的对象的object_id相同.
i3 = 10
s3 = "Digoal"
puts(i3.object_id)
puts(s3.object_id)
# 使用相同的值覆盖相同的变量, 看看object_id会不会变化, String类的对象的object_id会变化, Fixnum类的对象只要值一样, OBJECT_ID都一样.
i3 = 10
s3 = "Digoal"
puts(i3.object_id)
puts(s3.object_id)
执行结果 :
Fixnum
21
String
16221864
21
16221864
21
16221600
21
16221516
7. Indexing into a String
一个字符串, 其中的每个字符都有一个标记, 从0开始. 来看个例子 :
执行结果 :
注意1.8中用s[x]输出的是字符的ASCII值, 1.9输出的是字符本身. 如果要在1.9中输出ASCII怎么办呢, 用ord方法.
执行结果 :
还有一个玩法 :
执行结果 :
s = "Hello"
length = s.length
(0...length).each { # 三个点的Range类不包含最大值.
|x|
puts(s[x])
}
执行结果 :
H
e
l
l
o
注意1.8中用s[x]输出的是字符的ASCII值, 1.9输出的是字符本身. 如果要在1.9中输出ASCII怎么办呢, 用ord方法.
s = "Hello"
puts(s[0])
puts(s[0].ord)
执行结果 :
H
72
还有一个玩法 :
s = "Hello , I'm Digoal"
puts(s[0,4]) # 从0开始, 输出4个字符.
puts(s[-6,6]) # 从倒数第6个开始, 输出6个字符.
puts(s[(1...4)]) # 从1到4, 不包括4.
puts(s[(1..4)]) # 从1到4, 包括4
puts(s[(-6..-1)]) # 从-6到-1. 包括-6和-1
执行结果 :
Hell
Digoal
ell
ello
Digoal
接下来列举一些String类的方法 :
当然你可以使用String.methods打印出来看看到底有多少方法, 然后到API里面去学习它们的用法 :
输出结果 :
8. chomp(safer) and chop
s = "Hello , I'm Digoal"
puts(s.length)
puts(s.reverse!)
puts(s.reverse)
puts(s.upcase)
puts(s.capitalize)
puts(s.swapcase)
puts(s.downcase)
puts(s.insert(7,"NOT ")) # 注意这里的7是从0开始的哦,不是从1开始的. 是在index 7 之前插入的意思.
puts(s.squeeze)
puts(s.split)
输出结果 :
18
laogiD m'I , olleH
Hello , I'm Digoal
LAOGID M'I , OLLEH
Laogid m'i , olleh
LAOGId M'i , OLLEh
laogid m'i , olleh
laogiD NOT m'I , olleH
laogiD NOT m'I , oleH
laogiD
NOT
m'I
,
olleH
8. chomp(safer) and chop
先介绍一个$/ , 默认是\n. ASCII码=10. 这个字符串可以修改, 用于gets()时, 表示$/以后的字符不接收. $/本身接收 .
用在chomp()方法, 在末尾时可以去除这个字符串.
执行结果 :
chomp用于去除字符串末尾的\n, \r 或 \r\n. 或者$/, \n$/, \r$/, \r\n$/
执行结果 :
chop则是用于去除最后一个字符的, 不管是什么字符.
执行结果 :
再举一个gets()的例子 :
puts($/.class)
puts($/.ord)
执行结果 :
String
10
chomp用于去除字符串末尾的\n, \r 或 \r\n. 或者$/, \n$/, \r$/, \r\n$/
$/ = "ok"
puts("let's go0ok".chomp())
puts("let's go1\r\nok".chomp())
puts("let's go2\nok".chomp())
puts("let's go3\rok".chomp())
puts("let's go4\r".chomp())
puts("let's go5\n".chomp())
puts("let's go6\r\n".chomp())
# 以下则不能全部去除
puts("let's go7\n\r".chomp())
puts("let's go8ok\n".chomp())
puts("let's go9ok\r\n".chomp())
执行结果 :
let's go0
let's go1
let's go2
let's go3
let's go4
let's go5
let's go6
let's go7
let's go8ok
let's go9ok
chop则是用于去除最后一个字符的, 不管是什么字符.
$/ = "ok"
puts("let's go0ok".chop())
执行结果 :
let's go0o
再举一个gets()的例子 :
#!/opt/ruby/bin/ruby
$/ = "ok"
s = gets()
puts(s)
输入 :
jfjjsj
nioooo few ok ffewww good ok回车, # 第一个ok就表示记录结束了.
执行结果 :
jfjjsj
nioooo few ok
9. Format Strings ( printf )
printf()方法的格式化输出 :
执行结果 :
10. Range
%d – decimal number
%f – floating-point number
%o – octal number
%p – inspect object
%s – string
%x – hexadecimal number
printf( "%f\n", 10.12945 )
printf( "%0.2f\n", 10.12945 )
printf("d=%d f=%f o=%o x=%x s=%s\n", 10, 10, 10, 10, 10)
printf("0.04f=%0.04f : 0.02f=%0.02f\n", 10.12945, 10.12945)
class Myclass
def initialize(a,b)
@x = a
@y = b
end
attr_accessor( :x, :y )
end
ob1 = Myclass.new('digoal','zhou')
printf("inspect ob1: %p.\n",ob1)
执行结果 :
10.129450
10.13
d=10 f=10.000000 o=12 x=a s=10
0.04f=10.1295 : 0.02f=10.13
inspect ob1: #<Myclass:0x1fb0960 @x="digoal", @y="zhou">.
10. Range
Range在Ruby中非常有意思, 在PostgreSQL 中用generate_series函数可以产生一连串的数字, 时间等.
在Ruby中用Range可以产生一串数字, 字符串, 浮点数等.
执行结果 :
把Range对象转换成Array对象 : (注意浮点型的Range对象不可以转换成Array对象, 会报错, 因为可能包含无穷数)
执行结果 :
11. Iterating with a Range
r1 = (1..10) # 两个点表示包含最大和最小值
puts( r1.class )
puts( r1 )
puts( r1.count )
r2 = (1...10) # 三个点表示不包含最大值
puts( r2.class )
puts( r2 )
puts( r2.count )
执行结果 :
Range
1..10
10
Range
1...10
9
把Range对象转换成Array对象 : (注意浮点型的Range对象不可以转换成Array对象, 会报错, 因为可能包含无穷数)
r1 = (1..10)
r2 = ('abc'..'def')
a1 = r1.to_a # to_a方法用于将Range对象转换成Array对象.
a2 = r2.to_a
puts(a1.class)
puts(a2.class)
puts(a1)
执行结果 :
Array
Array
1
2
3
4
5
6
7
8
9
10
11. Iterating with a Range
其实Range和Array, Hash类型都有Iterate操作的. 来看个例子 :
执行结果 :
r1 = ('a'..'z')
r1.each { # 一个块,块非对象
|x| # 这是一个BLOCK内的变量.
print(x)
}
执行结果 :
abcdefghijklmnopqrstuvwxyz
12. Multi-line Strings ( <<EODOC )
多行字符串, 其实有点类似SHELL的玩法 :
执行结果 :
s1 = <<EODOC # 也可以写成<<'EODOC' , 则表示内部的字符串是用单引号包围的.
The first line.
The second line.
The third line.
... and so on
EODOC # EODOC必须在行首, 如果要不放行首, 可以在前面定义<<EODOC时改用<<-EODOC. 或者<<-'EODOC'
puts(s1)
执行结果 :
The first line.
The second line.
The third line.
... and so on
当然也可以不叫EODOC, 例如<<EOF也行, 结束时使用EOF.
13. String Literals
这个玩法也和有意思, 和前面我们已经用到的%x//, %q//, %Q// 相似, 还有一些其他的玩法. 列举如下 :
【参考】
%q/ / # single-quoted
%Q/ / # double-quoted
%/ / # double-quoted
%w/ / # array
%W/ / # array double-quoted
%r| | # regular expression
%s/ / # symbol
%x/ / # operating system command
p %q/dog cat #{1+2}/ #=> "dog cat \#{1+2}"
p %Q/dog cat #{1+2}/ #=> "dog cat 3"
p %/dog cat #{1+2}/ #=> "dog cat 3"
p %w/dog cat #{1+2}/ #=> ["dog", "cat", "\#{1+2}"]
p %W/dog cat #{1+2}/ #=> ["dog", "cat", "3"]
p %r|^[a-z]*$| #=> /^[a-z]*$/
p %s/dog/ #=> :dog
p %x/vol/ #=> " Volume in drive C is OS [etc...]"
【参考】
The Book Of Ruby
Ruby 1.9.3 API