删除与id匹配的行

时间:2017-11-20 10:34:00

标签: bash shell

我有以下包含 n 行的文件:

>name.1_i4_xyz_n
>name.1_i1_xyz_n
>name.1_i1_xyz_n
>name.1_i1_xyz_m
>name.1_i2_xyz_n
>name.1_i2_xyz_m
>name.1_i7_xyz_m
>name.1_i4_xyz_n
...

我想删除以m结尾的行。在示例中,输出将是:

>name.1_i4_n
>name.1_i4_n
...

请注意,我已删除了i2,因为它有两条记录,而其中一条记录以m 结尾。与i1相同。

有任何帮助吗?我想保持简单,只用一行代码即可。 这就是我到目前为止所做的:

$ grep "i._.*." < input.txt | sort -k 2 -t "_" | cut -d'_' -f1,2,4
>name.1_i1_m
>name.1_i1_n
>name.1_i1_n
>name.1_i2_m
>name.1_i2_n
>name.1_i4_n
>name.1_i4_n
>name.1_i7_m
...

4 个答案:

答案 0 :(得分:2)

删除以结尾的行:

$ grep -v m$ file
>name.1_i4_xyz_n
>name.1_i1_xyz_n
>name.1_i1_xyz_n
>name.1_i2_xyz_n
>name.1_i4_xyz_n

使用awk和2次运行来处理id的另一个解决方案:

$ awk 'BEGIN { FS="_" }  # set delimiter
NR==FNR {                # on the first run 
    if($0~/m$/)          # if it ends in an m
        d[$2]            # make a del array entry of that index
    next
}
($2 in d==0)' file file  # on the second run don't print if index in del array
>name.1_i4_xyz_n
>name.1_i4_xyz_n

单线版:

$ awk 'BEGIN{FS="_"}NR==FNR{if($0~/m$/)d[$2];next}($2 in d==0)' file file

答案 1 :(得分:1)

您可以使用awk

awk -F_ '{if(/m$/) a[$2]; else rows[++n]=$0}
END{for (i=1; i<=n; i++) {split(rows[i], b, FS); if (!(b[2] in a)) print}}' file

>name.1_i4_xyz_n
>name.1_i4_xyz_n

答案 2 :(得分:1)

如果i...部分没有出现在任何其他列中,您可以使用

grep -vFf <(grep -E 'm$' file | cut -d _ -f 2) file

<()内的部分会过滤掉所有以i...结尾的行m。在您的示例中:i1i2i7

外部grep采用文字搜索字符串列表(在<()内)并仅打印不包含任何搜索字符串的行。

答案 3 :(得分:0)

另一个awk提案。

awk '/_i4/&&!/_m$/' filterm.awk

>name.1_i4_xyz_n
>name.1_i4_xyz_n