希望清理一个小的红宝石脚本

时间:2010-04-13 23:22:00

标签: ruby

我正在寻找一种更惯用的方式来执行以下小红宝石脚本。

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

提前感谢任何建议。

3 个答案:

答案 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指定为肯定匹配,因此\wA-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