打印

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

本帖已经被作者加入个人空间 本主题由 quzhongwei 于 2008-6-18 11:54 设置高亮

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

一系列字符可以用一对单引号或双引号括起来成为字符串。php?name=Ruby" onclick="tagshow(event)" class="t_tag">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

    同样,下面的代码段也饶有趣味:

puts <<hello.insert(1, " hello")
  hello
hello


如果你把第二行的哪个hello顶格写将会发生IndexError,为什么?这当作这一讲的第一道作业题。
    更让你惊奇的是下面这个程序:

def ok(arg1, arg2, arg3)
    puts arg1
    puts arg2
    puts "OK, " + arg3
end

ok(<<hello, "Ruby", "Lua")  #要求写在一行上
    hello, Ruby
hello


只要下面这行:

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

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

[ 本帖最后由 quzhongwei 于 2008-6-19 02:29 编辑 ]
本帖最近评分记录
  • 5swords R币 +10 谢谢,这是我看到讲here document最好的一段 ... 2008-6-18 21:21

TOP

第1个问题应该是产生空串,第2题就当它是个下一行开始的串。
引用:
这一点对于用Ruby来做文档处理有很大的帮助,特别地,用这个技巧再结合序列化的相关技巧,你可以做出相当精彩的文稿处理。。
这一段很吸引人,不过文稿处理是什么东西?请多多指教。

TOP

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

TOP

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

执行,所以,当句子是:

puts <<hello.insert(1, " hello")
hello#第一个hello
hello#第二个hello


时,第一个hello作为了<<标识符的结束符,那么这个字符串为空,为空时在1位置插入一个元素就会引起

索引错误INDEXERROR,而如果第一个hello前面有空格的话则不当作<<标识符的结束符,而当作元素然后再把第二个hello当作<<标识符的结束符。等效于:

str = <<hello
 hello#第一个hello,如果前面没有空格则str内容结束,内容为空。
hello#第二个hello。
#这里str结束
str.insert(1,"hello")
#如果字符串第一个为空格,在1位置插入的话,会把元素往后移动,而不会出现覆盖第一
#个的现象。
put str



第二题没有看懂……


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

TOP

现在,请再看看原文。

TOP

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

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

TOP

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

TOP

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

TOP

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

TOP

2008-11-22 20:23 Crawled by CCBot/1.0 (+http://www.commoncrawl.org/bot.html) @38.103.63.61