仅删除包含特定模式的行

时间:2013-11-18 08:59:14

标签: unix scripting sed awk pattern-matching

我有一个带有许多功能的制表符分隔文件。我想删除信息量最少的行。具体来说,我想删除所有列中除了可以有yes或no之外的所有列都有问号(?)的行。我的文件看起来像

a   b   c   frequent
?   ?   ?   No
?   ?   1   Yes
1   ?   1   No
?   1   1   Yes
?   ?   ?   No
?   ?   ?   Yes

我想删除包含

的列
?   ?   ?   No 

?   ?   ?   Yes

我可以用

sed '/pattern/d' ./ file

我但是如何将它用于多个副本?可以有数百个列的解决方案,例如

sed '/?  ?  ?  No/d' ./ file

sed '/?  ?  ?  Yes/d' ./ file

不起作用。我希望我的输出看起来像

a   b   c   frequent
?   ?   1   Yes
1   ?   1   No
?   1   1   Yes

编辑1:对于制表符分隔文件中的列,第一列为序列号,最后一列为空格分隔的类标签。我想考虑倒数第二行的第二行,并删除包含所有问号的列。

No  a   b   c   itemname
1   ?   ?   ?   frying pan
2   ?   ?   1   t-shirt
3   1   ?   1   microwave oven
10  ?   1   1   forks and knives
11  ?   ?   ?   gold
12  ?   ?   ?   chain

想要的输出是

No  a   b   c   itemname
2   ?   ?   1   t-shirt
3   1   ?   1   microwave oven
10  ?   1   1   forks and knives

5 个答案:

答案 0 :(得分:3)

逃离?

sed '/\? +\? +\? +Yes/d' file

由于您的文件似乎是以多个空格分隔的空间,因此您需要+

或者如果你有tab

sed '/\?\t\?\t\?\tNo/d' file

awk解决方案,用于删除仅包含?

的行
awk '{for (i=1;i<NF;i++) if ($i!~"?") f=1} f {print;f=x}' file

或者使用aragaers方法,仅​​打印至少有一个1

的行
awk '/1/ || NR==1' file
a   b   c   frequent
?   ?   1   Yes
?   ?   1   Yes

答案 1 :(得分:3)

您可以尝试一步处理这两种情况

 sed -r '/(\?\s+){3}(Yes|No)/d' ./file

修改

关于每行?的数量,如果您想要“一个或多个”或使用{{1},则可以将{3}替换为+如果您想要“ 3或更多”之类的内容,或者您​​可以使用{3,}例如,如果您想说“介于3和5之间”< / p>

<强> EDIT2:

这是一个grep替代

{3,5}

注意

egrep -v '(\?\s+){3}(Yes|No)' ./fileToTest > outputFile 无效的原因是因为我们在检查了sed的帮助后需要sed我发现它是标志extended regex

答案 2 :(得分:2)

是否保证该列包含?1?如果是,只需删除所有内容,除非它至少包含一个1(并且不是第一行):

sed -n '1p; /1/p;' file

答案 3 :(得分:0)

使用awk

[ ~]$ cat test.txt 
a   b   c   frequent
?   ?   ?   No
?   ?   1   Yes
1   ?   1   No
?   1   1   Yes
?   ?   ?   No
?   ?   ?   Yes
[ ~]$ awk '!($0 ~ "?\\ *?\\ *?\\ *(Yes|No)"){print}' test.txt
a   b   c   frequent
?   ?   1   Yes
1   ?   1   No
?   1   1   Yes
[ ~]$ 

你也可以像这样使用egrep

[ ~]$ egrep  -v "\?\ *\?\ *\?\ *(Yes|No)" test.txt 
a   b   c   frequent
?   ?   1   Yes
1   ?   1   No
?   1   1   Yes

答案 4 :(得分:0)

关于您的上次更新,您可以按如下方式修改@Jotne的解决方案:

NR==1 {
    p=NF-2
    next
}
{
    for (i=1;i<=p;i++) {
        if (!( $(i+1)=="?")) f=1
    }
}
f {
    print
    f=x
}