简体   繁体   English

如何在Ruby中的同一行上grep多个字符串

[英]How to grep multiple strings on same line in Ruby

How can I modify my if statement to grep for multiple strings on the same line? 如何在同一行中将if语句修改为grep以获得多个字符串?

string = "1.1.1.1 example.com"
if File.readlines("/etc/hosts").grep(/#{string}/).any?
    exit
else
    File.open("/etc/hosts", "w") { |file| file.write(host_file)}
end

This is how it works in bash: 这是在bash中的工作方式:

if grep -q "1.1.1.1 example.com";
  then
      exit
else
    echo "1.1.1.1 example.com" >> /etc/hosts
fi

Personally I'd recommend using Resolv::Hosts instead of manually parsing the hosts file. 我个人建议使用Resolv :: Hosts而不是手动解析hosts文件。 Since it is built into the library it will cope with edge cases much better than anything you'll come up by yourself. 由于它是内置在库中的,因此比起您自己想做的任何事情,它对边缘情况的处理要好得多。

It starts with the location of the hosts file on different systems and goes on with situtations where you have entries like 1.1.1.1 example2.com example.com which would work but not match your grep expression. 它以不同系统上的hosts文件位置开始,并以情景方式继续,在该情景方式中,您可以使用1.1.1.1 example2.com example.com类的条目,这些条目可以工作但不匹配您的grep表达式。

From looking at " How to read lines of a file in Ruby " I think you need to use: 通过查看“ 如何在Ruby中读取文件行 ”,我认为您需要使用:

File.readlines('foo').each do |line|

In order to read all of the lines in the file, then perform your grep on each line. 为了读取文件中的所有行,然后在每一行上执行grep。

It isn't entirely clear what you're asking, but from the context it looks like you want a pattern that can be used to search for multiple entries in an array, since readlines returns an array containing the lines of the file. 目前还不清楚您要问的是什么,但是从上下文来看,您似乎想要一种可用于搜索数组中多个条目的模式,因为readlines返回一个包含文件行的数组。

A simple pattern example would be: 一个简单的模式示例为:

%w[foo bar baz].grep(/foo|bar/) # => ["foo", "bar"]

| means "or", so the pattern /foo|bar/ is looking for "foo" or "bar" . 表示“ or”,因此/foo|bar/正在寻找"foo" or "bar" grep will iterate over the array ['foo', 'bar'] , and finds both. grep将遍历数组['foo', 'bar'] ,并找到两者。

This isn't the entire solution because there are dragons waiting in the woods. 这不是完整的解决方案,因为树林中有巨龙在等待。 /foo|bar/ are actually matching substrings, not complete words: /foo|bar/实际上是匹配的子字符串,而不是完整的单词:

%w[food bartender].grep(/foo|bar/) # => ["food", "bartender"]

which is most likely not what you want. 这很可能不是您想要的。

To fix this we have to tell the regex engine to only find words: 为了解决这个问题,我们必须告诉正则表达式引擎仅查找单词:

%w[foo bar baz].grep(/\bfoo\b|\bbar\b/) # => ["foo", "bar"]
%w[food bartender].grep(/\bfoo\b|\bbar\b/) # => []

The \\b means a "word-boundary" which is the transition between a non-word character and a word character. \\b表示“单词边界”,它是非单词字符和单词字符之间的过渡。 \\w is the pattern used, and it's defined in the Regexp documentation . \\w是使用的模式,它在Regexp文档中定义。 I STRONGLY recommend reading about that as there are additional potential issues you can run into. 强烈建议您阅读有关内容,因为您可能会遇到其他潜在问题。 For our purposes though \\b and the default behavior is probably fine. 对于我们来说,虽然\\b和默认行为可能很好。

There's a lot of duplication in that little pattern though, and regular expressions let us trim out the replication: 在这个小模式中有很多重复项,而正则表达式使我们可以简化重复项:

%w[foo bar baz].grep(/\b(foo|bar)\b/) # => ["foo", "bar"]
%w[food bartender].grep(/\b(foo|bar)\b/) # => []

Using the parenthesis groups foo|bar into a capture-group, so the surrounding \\b will be applied to anything inside the parenthesis, reducing the noise. 通过将括号组foo|bar用作捕获组,可以将\\b应用于括号内的任何内容,从而降低了噪声。

Sometimes you don't want to actually capture the string, you just want to match it. 有时您不想真正捕获字符串,而只想匹配它。 If that's the case read about non-capturing groups in the documentation. 如果是这种情况,请在文档中阅读有关非捕获组的信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM