从文件

时间:2016-06-29 17:01:27

标签: bash shell awk sed grep

假设我有一个包含

的文件
abc aab100 100 cdc 20aaab aaaan
gshgds aab122 ghsgsd cdc aajksj aaasdan
gsgdsg hqusu jsdjsd jksjks jskdk
hjshj aab1jk uiuasu cdc 100ai bbcbxb
arta hyiosa jkulp nnnnnak cdc

我想匹配两个模式,如果两个模式都存在,我想删除该行。

所以我想删除的模式是aab1和cdc

在上面的文件中,这两个模式在第1行,第2行和第4行匹配。所以我想删除这3行

我可以使用grep作为

获得我想要的结果
grep -v 'aab1.*cdc' test.txt > test1.txt

即使我可以在同一个文件上执行此操作而无需通过

写入新文件
echo "$(grep -v 'aab1.*cdc' test.txt)" > test.txt

但是,如果不使用grep,还有其他更好/更快/更有效的方法吗?

由于

5 个答案:

答案 0 :(得分:1)

使用sed:

sed -i '/aab1.*cdc/d' file

-i选项用于编辑文件

答案 1 :(得分:1)

使用grep进行此类任务很好,代码的主要问题是命令替换,因为它会将grep的整个输出加载到内存中。考虑使用临时文件:

grep -v 'aab1.*cdc' test.txt > tmp.txt && mv tmp.txt test.txt

替代方案你可以使用sed和-i来启用inplace编辑(在引擎盖sed下也会使用临时文件):

sed -i '/aab1.*cdc/d' test.txt

还有sponge from moreutils会在打开输出文件之前吸收所有输入:

grep -v 'aab1.*cdc' test.txt | sponge test.txt

我无法告诉你它是如何实现的(使用临时文件或保存在内存中)

答案 2 :(得分:1)

sed -n  '/aab1.*cdc/!p' test > test1

也应该这样做

简而言之

我们检查每个LINE中的模式aab1.*cdc,如果它存在,我们不打印该行。标准OUT将重定向到名为test1

的文件

备注

  1. -n用于抑制正常输出
  2. /pattern/用于模式匹配。
  3. p用于打印行。因此!p否定了它。这会覆盖-n
  4. 使用perl

    perl -ni -e 'print unless (m/aab1/ && m/cdc/)' file
    

    备注

    1. -n用于抑制正常输出
    2. -i进行就地编辑
    3. -e允许您定义要由编译器执行的Perl代码。
    4. m/aab1/ && m/cdc/匹配(m)两种模式(&&)。{/ li>
    5. /stuff/如果两个图案都不存在,则会打印一行。
    6. 基于[ @tripleee's ]回答的另一个print unless解决方案

      sed

      备注

      这实现了此sed -n '/aab1/!{/cdc/!p}' test > test1 [ solution ]中提到的分支。

答案 3 :(得分:1)

拯救。

awk '!/aab1/ || !/cdc/' file

如果aab1未匹配或cdc不匹配,(执行默认操作,则)打印该行。

这很好地适用于您不关心匹配顺序的情况,如果您受限于单个正则表达式,则会很快变得复杂。

sed中的相同内容:

sed -e '/aab1/!b' -e '/cdc/d' file

概括为两个以上的模式,如果模式不匹配,请跳过此行的其余部分。如果我们到达最终的正则表达式,我们匹配所有模式,所以我们删除这一行。 (否则,我们打印。)

答案 4 :(得分:1)

如果指定了模式的顺序

$ awk '!/aab1.*cdc/' file

如果可能有任何订单

$ awk '!(/aab1/ && /cdc/)' file