【问题标题】:Removing lines matching a pattern删除与模式匹配的行
【发布时间】:2013-11-26 21:22:03
【问题描述】:

我想在文件中搜索模式并删除包含该模式的行。为此,我正在使用:

originalLogFile='sample.log'
outputFile='3.txt'
temp=$originalLogFile 

 while read line
 do
    echo "Removing" 
    echo $line
    grep -v "$line" $temp > $outputFile
    temp=$outputFile
done <$whiteListOfErrors

这适用于第一次迭代。对于第二次运行,它会抛出:

grep: input file ‘3.txt’ is also the output

任何解决方案或替代方法?

【问题讨论】:

    标签: linux shell loops grep


    【解决方案1】:

    以下应该是等价的

    grep -v -f  "$whiteListOfErrors" "$originalLogFile" > "$outputFile"
    

    【讨论】:

      【解决方案2】:
      originalLogFile='sample.log'
      outputFile='3.txt'
      tmpfile='tmp.txt'
      temp=$originalLogFile 
      while read line
      do
         echo "Removing" 
         echo $line
         grep -v "$line" $temp > $outputFile
         cp $outputfile $tmpfile
         temp=$tmpfile
      done <$whiteListOfErrors
      

      【讨论】:

        【解决方案3】:

        为此使用sed

        sed '/.*pattern.*/d' file
        

        如果您有多种模式,您可以使用-e 选项

        sed -e '/.*pattern1.*/d' -e '/.*pattern2.*/d' file
        

        如果您有GNU sed(Linux 上的典型),-i 选项很合适,因为它可以修改原始文件而不是写入新文件。 (但要小心处理,以免覆盖您的原始文件)

        【讨论】:

        • 前面和后面的.* 是多余的。无论如何,请选择@1_CR 的答案。
        • 是的grep在这里更好
        • 而且,像这样使用sed 并不能很好地处理多种模式。
        【解决方案4】:

        用这个来解决问题:

        while read line
        do
            echo "Removing" 
            echo $line
            grep -v "$line" $temp | tee $outputFile 
            temp=$outputFile
        done <$falseFailures
        

        【讨论】:

          【解决方案5】:

          简单的解决方案可能是使用交替文件;例如

          idx=0
          while ...
              let next='(idx+1) % 2'
              grep ... $file.$idx > $file.$next
              idx=$next
          

          更优雅的可能是创建一个大的grep 命令

          args=( )
          while read line; do args=( "${args[@]}" -v "$line" ); done < $whiteList
          grep "${args[@]}" $origFile
          

          【讨论】: