【问题标题】:Delete rows from 2 files after matching on first column在第一列匹配后从 2 个文件中删除行
【发布时间】:2018-02-07 17:32:39
【问题描述】:

我有两个文件 file1 和 file2,我想根据第一列(即 ID)删除不匹配的行

文件1

ID,NAME,ADDRESS
11,PP,LONDON
12,SS,BERLIN
13,QQ,FRANCE
14,LL,JAPAN

文件2

ID,NAME,ADDRESS
11,PP,LONDON
12,SS,BERLIN
13,QQ,FRANCE
16,WW,DUBAI

我想删除行

From File1
14,LL,JAPAN 

From File2
16,WW,DUBAI

使用 DIFF 命令我可以归档,但我想删除这些行。

还使用 AWK,我可以使用以下命令将这些行重定向到另一个文件。

awk 'FNR==NR{a[$1];next};!($1 in a)' File1 File2 > File3

但是不知道怎么删除。

我们可以这样做吗?

Using sed -id 's/AWK OUTPUT/g' File1

谢谢

【问题讨论】:

  • 文件排序了吗?
  • 我现在可以使用 sed 和 awk 删除行:sed -i '/'awk 'FNR==NR{a[$1];next};!($1 in a)' file2 file1'/d' file1
  • 不@Allan,文件未排序。
  • 之前尝试了 2 个小样本文件并且它有效,但是当我尝试具有 50K 记录的大文件时出现错误:sed -i '/'awk 'FNR==NR{a[$1];next};!($1 in a)' File2 File1'/d' File1 -bash: /usr /bin/sed: 参数列表太长

标签: unix awk sed


【解决方案1】:

你甚至不需要使用awk 这个操作grep 绰绰有余:

$ more file1 file2
::::::::::::::
file1
::::::::::::::
ID,NAME,ADDRESS
11,PP,LONDON
12,SS,BERLIN
13,QQ,FRANCE
14,LL,JAPAN
::::::::::::::
file2
::::::::::::::
ID,NAME,ADDRESS
11,PP,LONDON
12,SS,BERLIN
13,QQ,FRANCE
16,WW,DUBAI

$ grep -f <(grep -oP '^[^,]*,' file1) file2 > new_file2; grep -f <(grep -oP '^[^,]*,' file2) file1 > new_file1

$ more new_file*
::::::::::::::
new_file1
::::::::::::::
ID,NAME,ADDRESS
11,PP,LONDON
12,SS,BERLIN
13,QQ,FRANCE
::::::::::::::
new_file2
::::::::::::::
ID,NAME,ADDRESS
11,PP,LONDON
12,SS,BERLIN
13,QQ,FRANCE

解释

您使用grep -oP 从每行中提取带有逗号的 id,然后再次调用 grep 并传递模式列表,就好像它是分析第二个文件的文件一样,这将只打印匹配的行,您这样做与其他文件相同。

但是在进程结束时两个文件是相同的,所以你不需要运行grep -f &lt;(grep -oP '^[^,]*,' file2) file1 &gt; new_file1

另一种处理方式是使用以下命令:

$ grep -F -f <(paste -d'\n' <(cut -d',' -f1 file1 | sort -n) <(cut -d',' -f1 file2 | sort -n) | uniq -D | uniq) file1 > new_file1

$ more new_file1
ID,NAME,ADDRESS
11,PP,LONDON
12,SS,BERLIN
13,QQ,FRANCE

【讨论】:

  • 感谢您的命令,但我使用 AWK 根据第一列即 ID 比较两个文件
  • 是否可以提高此命令的性能,我的两个文件都有 50+k 条记录,并且此命令从最后 5 分钟开始运行并且仍在运行..
  • 对不起,我不知道你的文件有那么大,目前复杂度至少像 O(n^2) 让我想一个更好的解决方案!
  • 感谢艾伦,它工作正常,但有两个问题,第一个:它不会从文件中删除行,只会显示。第二是我仅根据第一列比较行,如果两个文件中的 ID 相同且名称不同,那么它也会忽略该行,我希望该行在文件中。
  • 这两个问题都可以轻松解决! ;-) 对于写作部分,您可以将标准输出重定向到一个新文件,或者您是否需要绝对删除最初的 2 个文件的内容?请注意,生成的文件将是相同的
【解决方案2】:

使用 tee 命令回答:

请注意,我已删除 ! 标志

 awk 'FNR==NR{a[$1];next};($1 in a)' File1 File2 | tee File1 

您可以使用您编写的原始 awk 命令,只需稍加改动即可

1)删除!

2) 使用 tee command 将 awk 结果 pip 到文件 - 仅当 | 之前的命令结束时,使用 | 才会执行下一个命令

【讨论】:

    【解决方案3】:

    使用 GNU awk 的 inplace edit(有关版本的讨论,请参阅链接):

    $ awk -i inplace '            # inplace edit modifies the original files
    BEGIN { FS="," }              # comma delimited files
    NR==FNR {                     # first file, hash all records and set value to 1
        a[$1]++
    }
    ($1 in a) && a[$1]==ARGIND {  # if index in a and it has been in each file read
        a[$1]++                   # ... increase count 
        print                     # ... and print to current file
    }' file1 file2 file1
    

    结果:

    $ cat file1
    ID,NAME,ADDRESS
    11,PP,LONDON
    12,SS,BERLIN
    13,QQ,FRANCE
    $ cat file2
    ID,NAME,ADDRESS
    11,PP,LONDON
    12,SS,BERLIN
    13,QQ,FRANCE
    

    注意:就地编辑会修改原始文件,因此请注意。如果您想在不使用原始文件副本的情况下对其进行测试,您可以删除 -i inplace 并将 print 替换为 print FILENAME, $0

    处理第一个文件时,每个 id 被散列到 a,其值增加到 1,因此输出到 file1,使其保持原始形式(如果没有重复的 id)。对于在 a 中找到的第二个文件 ID,将增加并打印回 file2,并且第二次处理适用于 file1 的文件。

    【讨论】:

    • 出现语法错误。用法:awk [POSIX 或 GNU 样式选项] -f progfile [--] 文件 ... 用法:awk [POSIX 或 GNU 样式选项] [--] '程序文件...
    • awk -V给你哪个版本?需要 4.1.0(请参阅链接)。
    • 我正在使用 ]# awk -V GNU awk 4.0.2
    • 这就是原因。是时候升级了。
    猜你喜欢
    • 1970-01-01
    • 2021-10-16
    • 1970-01-01
    • 2019-09-08
    • 1970-01-01
    • 2016-10-20
    • 1970-01-01
    • 2019-01-13
    • 1970-01-01
    相关资源
    最近更新 更多