删除文件中的每个匹配项

时间:2018-06-18 12:04:13

标签: awk sed

假设我有一个包含此格式内容的文件:

6 8
6 9
12 20
6
8
9
12
20
35

如果在下一行中找到了数字(从第1列或第2列),我想删除所有行,无论它是在第一列还是第二列,包括找到初始数字的行。

所以我应该这样做:

35

我尝试过使用

awk '{for(i=1;i<=NF;i++){if($i in a){next};a[$i]}} 1' 

有一种简单的方法吗?

5 个答案:

答案 0 :(得分:3)

这一行应该有所帮助:

awk 'NR==FNR{a[$0]++;next}{for(i=1;i<=NF;i++)if(a[$i]>1)next}7' 
     RS=" |\n" file RS="\n" file

使用此输入文件:

100 200 300
6 8
6 9
12 20
6
8
9
12
20
35

上面的单行将输出:

100 200 300
35

答案 1 :(得分:3)

您想要查找仅出现一次的数字。让我添加&#34; 42&#34;与&#34; 35&#34;

在同一行的文件
$ cat file
6 8
6 9
12 20
6
8
9
12
20
35  42

查找仅出现一次的所有数字:

$ tr -s "[:blank:]" "\n" < file | sort -n | uniq -u
35
42

但是,它并没有在文件中显示,所以

$ grep -n -Fw -f <(tr -s "[:blank:]" "\n" < file | sort -n | uniq -u) file
9:35  42

我添加了-n选项仅用于效果,以显示我们从文件中获得第9行。

答案 2 :(得分:2)

您最初编写的代码在以下条件下完美运行:打印当前行,当且仅当任何之前的行没有在当前行中列出的数字时。但是,您不要求上一个,而是下一个

简单的解决方案是输入tac并返回tac

$ tac <file> | awk '{for(i=1;i<=NF;i++){if($i in a) next;a[$i]}}1' | tac

如果您想使用单个awk,那么您必须先存储这些行并在之后处理它们,因为它还有点麻烦:

  • 你需要计算一个数字出现的次数
  • 并且您需要双通算法(通过运行文件两次或将其存储在内存中)

这为您提供以下内容:

双通:

$ awk '(NR==FNR){ for(i=1;i<=NF;i++) a[$i]++; next }'
       { b=0; for(i=1;i<=NF;i++) b+=--a[$i] }
       !b; <file> <file>

<强>存储器

$ awk '{ m[NR]=$0; for(i=1;i<=NF;i++) a[$i]++; next }
       END { for (n=1;n<=NR;++n) {
               b=0; $0=m[n];
               for(i=1;i<=NF;i++) b+=--a[$i]
               if (!b) { print }
             }
           }' <file>

这会输出预期的:

6
8
9
12
20
35

如果你想要删除所有包含一个数字的行,这些数字在文件中显示的更多,那么你只需:

$ awk '(NR==FNR) { for(i=1;i<=NF;i++) a[$i]++; next }
       { b=1; for(i=1;i<=NF;i++) b = b && (a[$i]==1) }
       b' <file> <file>
来自您输入的

注意:您可能还会遇到Windows \r问题,因此您可能希望在所有内容之前执行gsub("\r","")

答案 3 :(得分:1)

awk中的另一个,处理数据一次:

awk ' 
{
    for(i=1;i<=NF;i++) {          # process numbers in record
        r[$i]=r[$i] NR OFS        # add NR on a record list array
        if(p=split(r[$i],t)>1) {  # if there are more than one record in r
            for(j in t)           # delete records on the list
                delete a[t[j]]
            f=1                   # flag up 
        }
    }
    if(f=="")                     # if flag is down
        a[NR]=$0                  # store current record 
    f=""                          # reset flag
}
END {
    for(i=1;i<=NR;i++)            # in the end
        if(i in a)                # print all records stored
            print a[i]
}' file
35

修订版:

awk '
{
    for(i=1;i<=NF;i++) {
        if($i in r) {             # just store the NR of last duplicate
            delete a[r[$i]]
            f=1
        }
        r[$i]=NR
    }
    if(f=="") 
        a[NR]=$0
    f=""
}
END {
    for(i=1;i<=NR;i++)
        if(i in a)
            print a[i]
}' file
35

答案 4 :(得分:0)

您可以尝试这样的事情:

cat yourFile | tr ' ' '\n' | sort  | uniq -u