【问题标题】:How to use `while read -r line` while also checking if another file is not empty in BASH?如何在 BASH 中检查另一个文件是否为空的同时使用“while read -r line”?
【发布时间】:2014-03-31 22:02:45
【问题描述】:

我有一个while循环,简化如下:

while read -r line
do
    (delete some lines from file2.txt)
done < file.txt

如果file2.txt 为空,则此while 循环不再需要运行。

换句话说,我需要这个:

while read -r line AND file2.txt IS NOT EMPTY
do
    (delete some lines from file2.txt
done < file.txt

我尝试将while read -r line-s file2.txt 结合,但结果不起作用:

while [ read -r line ] || [ -s file2.txt ]
do
    (delete some lines from file2.txt)
done < file.txt

如何使用此 while 循环读取文件中的行,同时检查另一个文件是否为空?

【问题讨论】:

  • 您可以在 (delete some lines from file2.txt) 之后的原始 while 循环中放置一个 if (file2.txt is empty check) ; then break ; fi。我不确定您是如何从file2.txt 中删除行的,因此不确定您要进行什么“空”检查。
  • 我使用sed -i "/$line/d" ./file2.txtfile2.txt 中删除内容,这是在while 循环进行时发生的。发生的情况是,file2.txt 很快就会变空,但while loop 会不必要地持续几分钟。如果我将if 条件放在while 条件中,我认为脚本不会加速。
  • @Village 还有什么东西在这个文件中添加了行吗?您是否正在实施队列?如果您愿意,您可能需要考虑使用 fifo(请参阅mkfifo)。我只是不确定sed -i 是否足够原子

标签: bash while-loop


【解决方案1】:

将读取和测试组合为:

while read -r line && [ -s file2.txt ]
do
  # (delete some lines from file2.txt)
  echo "$line"
done <file.txt

这将在每次循环迭代之前检查file2.txt 是否为非空。

【讨论】:

  • 我会将[ 测试移到read 表达式之前,以避免不必要地消耗另一行标准输入。
【解决方案2】:

就我个人而言,我会这样做

while read -r line
do
    [ ! -s file2.txt ] && break
    # (delete some lines from file2.txt)
done <file.txt

严格来说,我的解决方案与其他任何解决方案没有什么不同或更好,但这只是个人喜好问题。我不喜欢在循环中混合其他条件,该循环正在做一些简单的事情,比如从文件中读取行。我发现它使代码的可读性降低。其他人无疑会不同意,甚至可能建议在循环中依赖 break 是不好的做法,但我发现它可以让我快速掌握正在发生的事情,而不必放慢速度并在心理上处理条件,就像当您在周边视觉中看到停车标志时,您会停下来,而无需直接看标志并阅读字母“STOP”来理解它。 while read -r line 之类的东西是如此常见的习语,以至于它们本质上是普通街道标志的编程等价物。您可以立即识别它们,而无需在精神上解析它们。无论如何,就像我说的,这只是我个人的看法。随意不同意。

【讨论】:

    【解决方案3】:

    稍微优化一下乔给出的答案

    while [ -s file2.txt ] && read -r line
    do
      # (delete some lines from file2.txt)
    done <file.txt
    

    【讨论】:

      【解决方案4】:

      对 cat 的无用使用会简化这里的事情:

      while read -r line
      do
          (delete some lines from file2.txt)
      done < <(test -s file2.txt && cat file.txt)
      

      $ cat file.txt
      foo
      bar
      baz
      $ cat file2.txt
      something
      $ while read -r line; do echo "$line"; done < <(test -s file2.txt && cat file.txt)
      foo
      bar
      baz
      $ > file2.txt
      $ while read -r line; do echo "$line"; done < <(test -s file2.txt && cat file.txt)
      $
      

      【讨论】:

      • 如果它真的有用的话,不是那么没用,是吗? :)
      【解决方案5】:

      你可以这样做:

      while read -r lf1 && [[ -s "path/to/file2" ]] && read -r lf2 <&3; do 
         echo "$lf1"; echo "$lf2"
      done <file1 3<file2
      

      只是一个示例,您可以在 while 块中添加自己的代码。

      测试:

      <~/Temp>$ cat file1
      line from file1
      line2 from file1
      

      <~/Temp>$ cat file2
      I am not empty
      Yep not empty
      

      <~/Temp>$ while read -r lf1 && [[ -s "/Volumes/Data/jaypalsingh/Temp/file2" ]] && read -r lf2 <&3; do echo "$lf1"; echo "$lf2"; done <file1 3<file2
      line from file1
      I am not empty
      line2 from file1
      Yep not empty
      

      <~/Temp>$ >file2
      

      <~/Temp>$ while read -r lf1 && [[ -s "/Volumes/Data/jaypalsingh/Temp/file2" ]] && read -r lf2 <&3; do echo "$lf1"; echo "$lf2"; done <file1 3<file2
      <~/Temp>$ 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-04-15
        • 2012-08-17
        • 1970-01-01
        • 2014-08-23
        • 2019-12-16
        • 1970-01-01
        • 2022-01-27
        • 2017-04-27
        相关资源
        最近更新 更多