我正在寻找一种更惯用的方式来执行以下小红宝石脚本。
File.open("channels.xml").each do |line|
if line.match('(mms:\/\/{1}[a-zA-Z\.\d\/\w-]+)')
puts line.match('(mms:\/\/{1}[a-zA-Z\.\d\/\w-]+)')
end
end
提前感谢任何建议。
答案 0 :(得分:3)
原文:
File.open("channels.xml").each do |line|
if line.match('(mms:\/\/{1}[a-zA-Z\.\d\/\w-]+)')
puts line.match('(mms:\/\/{1}[a-zA-Z\.\d\/\w-]+)')
end
end
可以改为:
m = nil
open("channels.xml").each do |line|
puts m if m = line.match(%r|(mms://{1}[\w\./-]+)|)
end
File.open
可以更改为open
。
if XYZ
puts XYZ
end
只要x发生在if语句之前的当前作用域中的某个位置,就可以将更改为puts x if x = XYZ
。
Regexp '(mms:\/\/{1}[a-zA-Z\.\d\/\w-]+)'
可以稍微重构一下。使用%rXX
表示法,您可以创建正则表达式而无需太多反斜杠,其中X是任何匹配的字符,例如(
和)
或上面的示例{{1} 1}} |
。
此字符类|
(读取:A到Z,不区分大小写,句点字符,0到9,正斜杠,任何单词字符或短划线)有点多余。 [a-zA-Z\.\d\/\w-]
表示“单词字符”,即A-Za-z0-9和下划线。由于您将\w
指定为肯定匹配,因此\w
和A-Za-z
是多余的。
使用这两个清理,可以将Regexp更改为:\d
如果你想避免使用奇怪的%r|(mms://{1}[\w\./-]+)|
范围巫术,这也会奏效,但不太惯用:
m = nil
或更长但更易阅读的版本:
open("channels.xml").each do |line|
m = line.match(%r|(mms://{1}[\w\./-]+)|) and puts m
end
答案 1 :(得分:1)
一种非常容易理解的方法就是存储匹配的结果,然后只有在匹配时才打印:
File.open("channels.xml").each do |line|
m = line.match('(mms:\/\/{1}[a-zA-Z\.\d\/\w-]+)')
puts m if m
end
如果你想开始聪明(并且代码不太可读),请使用$&
这是接收匹配变量的全局变量:
File.open("channels.xml").each do |line|
puts $& if line.match('(mms:\/\/{1}[a-zA-Z\.\d\/\w-]+)')
end
答案 2 :(得分:1)
就个人而言,我可能只是使用POSIX grep
命令。但Ruby中也有Enumerable#grep
:
puts File.readlines('channels.xml').grep(%r|mms://{1}[\w\./-]+|)
或者,您可以使用从Perl继承的Ruby的一些文件和行处理魔法。如果将-p
标志传递给Ruby解释器,它将假定您传入的脚本包含while gets; ...; end
,并且在每个循环结束时它将打印当前行。然后,您可以使用$_
特殊变量来访问当前行,如果您不想打印该行,请使用next
关键字跳过循环的迭代:
ruby -pe 'next unless $_ =~ %r|mms://{1}[\w\./-]+|' channels.xml
基本上,
ruby -pe 'next unless $_ =~ /re/' file
相当于
grep -E re file