【问题标题】:Check if file contains string检查文件是否包含字符串
【发布时间】:2012-01-14 13:19:47
【问题描述】:

所以我在这里找到了这个问题,但是我在输出以及如何使用 if 语句处理它时遇到了问题。这是我的,但它总是说这是真的,即使文件中不存在monitor这个词

if File.readlines("testfile.txt").grep(/monitor/)
  do something
end

应该是 == "nil" 之类的东西吗?我对 ruby​​ 很陌生,不确定输出会是什么。

【问题讨论】:

  • 注意:如果文件大于可用内存,使用readlines 确实会导致问题。有关详细信息,请参阅“Why is slurping a file bad?”。

标签: ruby if-statement


【解决方案1】:

Enumerable#grep 不返回布尔值;它返回一个数组(如果不传递块,您将如何访问匹配项?)。

如果未找到匹配项,则返回一个空数组,[] 的计算结果为 true。您需要在if 语句中检查数组的大小,即:

if File.readlines("testfile.txt").grep(/monitor/).size > 0
  # do something
end

文档应该是您解决此类问题的第一个资源。

【讨论】:

  • 感谢这篇文章。你在这方面帮了我很多忙。但我想知道是否需要搜索路径?
  • @MZaragoza:取决于什么样的路径。我敢肯定,如果您搜索正则表达式以匹配路径,您会找到很多示例。
  • 我正在寻找一个看起来像“/www/assests/2015/09/18/someimage.png”的文件中的字符串,问题是还有其他图像名称“someimage.png”在其他目录中
  • 对于路径,您可能希望在 grep 中使用正则表达式。例如; File.readlines("/home/#{os_user}/.bash_profile").grep(%r{JAVA_HOME=\/opt\/Oracle\/jdk}).empty?
【解决方案2】:

我会使用:

if File.readlines("testfile.txt").grep(/monitor/).any?

if File.readlines("testfile.txt").any?{ |l| l['monitor'] }

虽然使用readlines 会将整个文件读入一个数组,但它存在可伸缩性问题。相反,使用foreach 将完成同样的事情,而不会出现可伸缩性问题:

if File.foreach("testfile.txt").grep(/monitor/).any?

if File.foreach("testfile.txt").any?{ |l| l['monitor'] }

有关可扩展性问题的更多信息,请参阅“Why is "slurping" a file not a good practice?”。

【讨论】:

  • +1 for any?,因为它会在找到第一个匹配项后立即结束,而不是处理每一行来查看是否匹配。
  • 请记住,这不是幂等的。连续运行两次将在第一次运行时返回true,在第二次运行时返回false。在再次运行之前,您需要 rewind 文件。
  • 不需要rewindreadlines 会自动打开和关闭文件,所以它总是从头开始读到最后。
  • 再次为any? 加1,不过为了快速澄清,一旦你找到匹配项就返回的方法是any? { ... } 而不是grep(...).any?。学到这个很难,应该密切关注:)
  • @SRack 你并不孤单。我做了同样的事情。我编辑了答案,将最好的方法放在首位,然后展示了备选方案,并说明了为什么每个备选方案都不如顶级方法。
【解决方案3】:

Grep 将为您提供所有找到的“监视器”的数组。但是你不想要一个数组,你想要一个布尔值:这个文件中是否有任何“监视器”字符串? 这个根据需要读取尽可能少的文件:

if File.open('test.txt').lines.any?{|line| line.include?('monitor')}
  p 'do something'
end

readlines 读取整个文件,lines 返回一个逐行执行的枚举器。

更新

#lines 已弃用,请改用 #each_line

  if File.open('test.txt').each_line.any?{|line| line.include?('monitor')}
    p 'do something'
  end

【讨论】:

    【解决方案4】:

    如果有人正在寻找一种解决方案来显示该字符串出现的文件的最后一行,那么就这样做

    File.readlines('dir/testfile.txt').select{|l| l.match /monitor/}.last 
    

    示例

    文件:

    monitor 1
    monitor 2
    something else
    

    你会得到

    monitor 2
    

    【讨论】:

      【解决方案5】:

      对于命令行实用程序,我通常会跳过 ruby​​,因为它们往往更快。

      `grep "monitor" "testfile.txt" > /dev/null`
      $?.success #=> true if zero exit status, false otherwise.
      

      【讨论】:

        猜你喜欢
        • 2012-02-21
        • 1970-01-01
        • 1970-01-01
        • 2011-09-05
        • 2020-04-15
        • 2011-11-09
        • 2013-05-18
        • 2012-06-30
        • 1970-01-01
        相关资源
        最近更新 更多