2017-09-06 57 views
0

假设多行文本文件file如果满足不同行上的两个条件,则删除行

$cat file 
foo bar baz 
foo bar baz qux 
foo bar baz quux # Line to be deleted 
foo bar quux 

我希望删除所有那些fullfill两个条件线:(a)该行包含关键字“QUUX”,和(b)的线是立即由包含一个线preceeded关键字“qux”。

$cat file | sought_command 
foo bar baz 
foo bar baz qux 
foo bar quux 

我很茫然作为UNIX工具可以应用到这样的双重条件(可能AWK,但我不确定),并希望建议。

编辑1: 一旦被通知awk是使用工具和在考虑的任务进一步,我要找专门为代码,可以很容易地被修改,使得条件(b)可以反转(即, “(b)如果有必要,该行不会立即包含关键字'qux'”的行)。

+1

无需不知所措:S /老/新=> sed和克/ RE/P => grep和别的(例如。)=> awk。现在 - 你在寻找字符串还是正则表达式比较以及部分或全部匹配? –

回答

0

这可能是你要寻找的依赖,如果你想字符串或正则表达式比较和部分或全部的比赛上。

1)删除行,如果它包含QUUX和前述之一包含qux:

$ awk '!(/quux/ && p~/qux/); {p=$0}' file 
foo bar baz 
foo bar baz qux 
foo bar quux 

2)删除行,如果它包含QUUX和前一个不包含qux:

awk '!(/quux/ && p!~/qux/); {p=$0}' file 

,如果你喜欢,以避免双重否定,布尔代数可以减少到:

awk '!/quux/ || p~/qux/; {p=$0}' file 

您喜欢的任何复合条件只需执行& & -ing和/或|| -ing和/或否定$ 0上的测试(隐含在/.../中)和p。

+0

我明白了。所以'awk'毕竟是工具。是的,字符串比较是我正在寻找的。感谢你及时的答复。 –

+0

短期随访:如果我想将条件(b)更改为“该行是** NOT **,紧接着包含关键字'qux'的行,则该怎么办?”。用awk单行程来实现会很简单吗? –

+1

这里没有任何答案进行字符串比较,它们都与部分匹配进行正则表达式比较。如果你匹配的文本('quux'和'qux')可以包含regexp元字符(例如'q。* x'),那么字符串/ regexp的区别很重要。是否允许部分匹配(例如'qux'匹配'fooquxbar'?)可能更相关。是的,任何改变都是微不足道的:'awk'!(/ quux/&& p!〜/ qux /); {p = $ 0}'文件'布尔代数可以简化为'awk'!/ quux/|| P〜/ qux /; {p = $ 0}'文件'。 –

0

AWK脚本,将你想要做什么:

$ cat tst.awk 
/quux/ && p { p=/qux/; next } 
{ p=/qux/ } 
{ print } 

与输入:

$ cat input.txt 
foo bar baz qux 
foo bar baz quux qux 
foo bar baz quux 
foo bar quux 

给出:

$ awk -f tst.awk input.txt 
foo bar baz qux 
foo bar quux 

后续问题是每当它连接时删除一行tains'quux'和前面的行确实是而不是包含'qux'。一个简单的否定p就是要做的。

cat tst2.awk 
/quux/ && !p { p=/qux/; next } 
{ p=/qux/ } 
{ print } 

与输入:

$ cat del.txt 
foo bar baz qux 
foo bar baz quux qux 
foo bar baz quux 
foo bar quux  # to be deleted 

给出:

awk -f tst2.awk del.txt 
foo bar baz qux 
foo bar baz quux qux 
foo bar baz quux 
+0

@MarcLambrichs我刚刚编辑我的问题,使其更具体。你的代码如何修改以允许条件(b)的逆转? –

0

您可以通过以下方式使用awk

awk '$4 ~/qux/ || $4 !~/quux/' file 

foo bar baz 
foo bar baz qux 
foo bar quux 
相关问题