Ruby正则表达式/模式匹配用于精确单词/字符串匹配

4

有一个简短的问题:我有一个像这样的文件:

ip-10-0-12-84.eu-west-1.compute.internal, master, instnum=1, Running
.....
.....
ip-10-0-26-118.eu-west-1.compute.internal, master_rabbit, instnum=4, Running
ip-10-0-26-116.eu-west-1.compute.internal, master_rabbit, instnum=5, Running
.....
ip-10-0-26-68.eu-west-1.compute.internal, sql_master, instnum=9, Running
ip-10-0-13-244.eu-west-1.compute.internal, nat, instnum=2, Running

我的目标是读取文件,跳过以#开头的注释、空行和包含natmaster的行。我尝试了以下代码:

open('/tmp/runnings.txt').each do |line|
    next if line =~ /(^\s*(#|$)|nat|master)/

这个方法大部分可行,但会把包含master_rabbitsql_master的行也删除。我该如何只选中master而不是其他任何组合?能否在同一行完成操作?谢谢!


搜索', master,'而不是仅仅是'master' :) - tessi
2
nat也是这样吗?还是你也想匹配national - Tim Pietzcker
@Tim Pietzcker:目前还没有需要国家级别,但这是一个好点。你的答案已经覆盖了这一点。 - MacUsers
@MacUsers Tim正在提问。这不是好或坏的观点。你的答案是什么? - sawa
@sawa:嗯,正如我之前说的那样:目前它并不是真正需要的,但也许未来会需要。 - MacUsers
3个回答

6

谢谢Tim,这正是我所需要的;做得很好。我知道有一种比我想象中更简单的方法。 - MacUsers

1
open("/tmp/runnings.txt").each_line
.grep(/\A(?!\s*#)(?!.*\bnat\b)(?!.*\bmaster\b).*\S/) do |line|
  ...
end

1
我觉得用正则表达式解决问题并不是一个合适的方式。虽然现在可以解决问题,但以后很难理解,如果需要排除新的关键词,修改也会更加困难。
我喜欢这种解决问题的方式:
FILE_PATH = '/tmp/runnings.txt'
keywords  = ['nat', 'master']
empty_lines_and_comments     = ->x{ x.chomp.empty? or x.start_with?('#') }
lines_containing_bad_keyword = ->x{ keywords.include? x[1] } # Keywords at index 1

data = File.readlines(FILE_PATH)
           .reject(&empty_lines_and_comments)
           .map{|line| line.chomp.split(', ')}
           .reject(&lines_containing_bad_keyword)

考虑到所涉及文件的非常静态的特性,我认为目前没有任何需要额外关键字的必要,但了解正确的操作方式总是好的。感谢提供代码,我肯定会有所用处。干杯! - MacUsers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接