#{ok}" # 输出:Hello -> OKputs 'Hello -> # ... Ruby中文社区论坛 Ruby中文社区提供Ruby,ruby on rails等相关技术的讨论和资源下载,讨论Ruby语言,提供Ruby教程,学习资料,电子书籍,培训教材,视频教程等下载。 - Discuz! Archiver" />

查看完整版本: A.7 字符串--(附:Here Document处理技巧)

quzhongwei 2008-6-18 11:52

A.7 字符串--(附:Here Document处理技巧)

一系列字符可以用一对单引号或双引号括起来成为字符串。Ruby的字符串是String类的对象。单引号和双引号括起来的字符串并不完全相同,比如:

ok = "OK"

puts "Hello -> #{ok}"  # 输出:Hello -> OK
puts 'Hello -> #{ok}'  # 输出:Hello -> #{ok}

        从上面的例子可以看出:单引号的字符串会进行较少的表达式替换,双引号的字符串会进行更多的表达式替换。
        单引号和双引号的多行字符串表示也可以换为用%表示。我们来看看下面的多行字符串表示:

OK = "Ruby"

puts %/#{OK}
.hello/

puts %Q[#{OK}
.hello]

puts %q{#{OK}
.hello}

puts %(/#{OK}
.hello)

        我们发现,%表示多行字符串时,单独一个%和%Q的作用是一样的——同双引号功能一样。%q的功能和单引号表示一样。另外在这种表示法中你可以在%、%Q、%q后面用{{[和]}}括号把多行字符串括起来。
        在Ruby中字符串的处理非常重要,字符串类中也定义了很多的处理字符串的方法。同时Ruby也定义了一种多行字符串的表示方式,被称为Here Document。它的语法格式如下:

<<标识字符串
    内容
标识字符串

        这里标识字符串要紧接着<<书写,并且前后两个标识字符串在形式上要相同:

ok = "Ruby"

puts <<ok
    hello, world!
----ya!ya.   #{ok}
ok

        除非,你用单引号和双引号把第一个标识字符串括起来,来执行特定的替换功能:

ok = "Ruby"

puts <<"ok"
    hello, world!
----ya!ya.   #{ok}
ok

puts <<'ok'
    hello, world!
----ya!ya.   #{ok}
ok

        上面两段代码说明:标识符被双引号括起来和没有括起来在效果上是一样的。
        一般情况下结尾的标识符必须顶格写,当然在<<后面加上- (减号)时,结尾的标识符可以缩进书写:

ok = "Ruby"

puts <<-ok
    hello, world!
----ya!ya.   #{ok}
               ok

        下面的代码也许会让你觉得奇怪:

ok = "Ruby"
puts <<-ok, <<-hello
    hello, world!
----ya!ya.   #{ok}
ok
      #{ok}
   hello

它输出:

    hello, world!
----ya!ya.   Ruby
      Ruby
        Ruby的作者是这样解释的:<<标识符和结尾的标识符并不是一个整体,而“<<标识符”代表的就是多行字符串的内容,这些内容从“<<标识符”的第二行开始,到结尾字符串为止。这就出现了一个很有意思的语法:

def hello(str1, str2)
    puts str1
    puts str2
end

hello("Ruby", <<-hello)
    hello!
                              hello

        同样,下面的代码段也饶有趣味:[code]puts <<hello.insert(1, " hello")
  hello
hello[/code]如果你把第二行的哪个hello顶格写将会发生IndexError,为什么?这当作这一讲的第一道作业题。
        更让你惊奇的是下面这个程序:[code]def ok(arg1, arg2, arg3)
    puts arg1
    puts arg2
    puts "OK, " + arg3
end

ok(<<hello, "Ruby", "Lua")  #要求写在一行上
    hello, Ruby
hello[/code]只要下面这行:

ok(<<hello, "Ruby", "Lua")

        不分开行写——即就在一行上面,Ruby解释器会正常工作!(为什么?本讲第二个作业题。)
        这一点对于用Ruby来做文档处理有很大的帮助,特别地,用这个技巧再结合序列化的相关技巧,你可以做出相当精彩的文稿处理。。

[[i] 本帖最后由 quzhongwei 于 2008-6-19 02:29 编辑 [/i]]

5swords 2008-6-18 21:20

第1个问题应该是产生空串,第2题就当它是个下一行开始的串。

[quote]这一点对于用Ruby来做文档处理有很大的帮助,特别地,用这个技巧再结合序列化的相关技巧,你可以做出相当精彩的文稿处理。。[/quote]

这一段很吸引人,不过文稿处理是什么东西?请多多指教。

neohsiao 2008-6-18 22:10

太好了,我还在新手区发了Here document的问题呢,终于有解答了,运气好!:lol

neohsiao 2008-6-19 00:01

第一个问题,是因为<<标识符是hello,而句子hello.insert(1, " hello")将在here document建议以后

执行,所以,当句子是:[code]puts <<hello.insert(1, " hello")
hello#第一个hello
hello#第二个hello[/code]时,第一个hello作为了<<标识符的结束符,那么这个字符串为空,为空时在1位置插入一个元素就会引起

索引错误INDEXERROR,而如果第一个hello前面有空格的话则不当作<<标识符的结束符,而当作元素然后再把第二个hello当作<<标识符的结束符。等效于:[code]str = <<hello
hello#第一个hello,如果前面没有空格则str内容结束,内容为空。
hello#第二个hello。
#这里str结束
str.insert(1,"hello")
#如果字符串第一个为空格,在1位置插入的话,会把元素往后移动,而不会出现覆盖第一
#个的现象。
put str[/code][size=5]
第二题没有看懂……[/size]:L

[[i] 本帖最后由 neohsiao 于 2008-6-19 00:05 编辑 [/i]]

quzhongwei 2008-6-19 02:31

现在,请再看看原文。

liuxueming 2008-7-1 16:28

只要下面这行:
ok(<<hello, "Ruby", "Lua")

    不分开行写——即就在一行上面,Ruby解释器会正常工作!
------------------------------------------------------------
这条语句执行报错!
can't find string "hello" anywhere before EOF
他的报错是正确的。

vintager 2008-7-7 17:16

可以把<<后面的hello看作是占位符,实际内容在下一行到hello之间。

weywong 2008-8-26 21:59

Here Document够绕人的。例子中的代码,仔细想想完全合乎逻辑;可要自己写实在写不出来。

punkpopb 2008-8-30 01:38

第一题的意思我没了,就也是第2行的hello如果顶格写的话就成了标识符hello的结束,所以这时候实际上Here Document对象是个空字串,所以对空字串使用insert方法自然会产生错误!
不过为什么我安装的ruby186-26(windows xp(pack 2)),在SciTE中运行这段代码(第2行hello顶格)却是可以通过的,并且结果是正确的!
不明白这是怎么一回事,但是如果去掉第3行的hello就出现老师所说的错误。
页: [1]
查看完整版本: A.7 字符串--(附:Here Document处理技巧)