【问题标题】:Comparing two files using awk and printing contains which are matching from other files使用 awk 比较两个文件并打印包含与其他文件匹配的文件
【发布时间】:2012-09-25 02:36:55
【问题描述】:

我有两个文件:

file1.txt

919167,hutch,mumbai
919594,idea,mumbai

file2.txt

919167000000
919594000000 

输出

919167000000,hutch,mumbai
919594000000,idea,mumbai

如何使用 AWK 实现这一点?我有一个巨大的电话号码文件,需要像这样进行比较。我相信 Awk 可以处理它;如果没有,请告诉我该怎么做。


额外定义

  • 公共部分总是 6 位数字吗? 是的,总是 6。
  • 这两个文件是否已经排序? file1 没有排序。 file2 可以排序。
  • 文件 2 中的尾随数字是否始终为零? 不,这些是电话号码,可能会有所不同,这样做的目的是获取电话号码的系列信息。
  • 文件 1 包含给定数字的 3 条记录,而文件 2 包含 2 条记录,或者是一对一的,是否存在危险? 这是一对一的。 文件 1 中是否存在与文件 2 中不匹配的记录,反之亦然?_ 是的。
  • 如果是这样,您想查看不匹配的记录吗? 是的,我想要两条记录。

扩展数据

file1.txt

919167,hutch,mumbai
919594,idea,mumbai
918888,airtel,karnataka

file2.txt

919167838888
919594998484
919212334323

预期输出:

919167838888,hutch,mumbai
919594998484,idea,mumbai
919212334323,nomatch,nomatch

【问题讨论】:

  • 公共部分总是6位数字吗?这两个文件是否已经排序?显示的数据已排序。文件 2 中的尾随数字是否始终为零?文件 1 包含三个给定数字的记录,而文件 2 包含 2 条记录,或者是一对一的,是否存在危险?文件 1 中是否有记录而文件 2 中没有匹配项,反之亦然?如果是这样,您想查看不匹配的记录吗?
  • @user1719039:请查看我所做的更改。

标签: linux awk


【解决方案1】:

正如我在评论中指出的那样,需要大量未说明的信息才能给出明确的答案。但是,我们可以做出一些似是而非的猜测:

  1. 通用数字是文件 2 的前 6 位数字(我们不关心尾随数字,而只是将它们复制到输出中)。
  2. 文件按顺序排序。
  3. 如果任一文件中有不匹配的记录,这些记录将被忽略。

选择的工具大概是sedjoin

sed 's/^\([0-9]\{6\}\)/\1,\1/' file2.txt |
join -t, -o 1.2,2.2,2.3 - file1.txt

这将编辑file2.txt 以创建一个以逗号分隔的第一个字段,其中包含 6 位电话号码,后跟该行的所有其余部分。输入被馈送到join 命令,该命令连接到第一列,并从file2.txt 输出“其余行”(第2 列),从file1.txt 输出第2 列和第3 列。

如果电话号码是可变长度的,那么匹配操作会非常复杂。为此,我会使用 Perl(或 Python)来完成这项工作。如果数据未排序,则可以在输入命令之前对其进行排序。如果你想要不匹配的记录,你可以在join的选项中指定如何处理。


现在可以获得所需的额外信息。关键信息是 6 位数字是固定的——唷!由于您使用的是 Linux,我假设 bash 可用于“进程替换”:

sort file2.txt |
sed 's/^\([0-9]\{6\}\)/\1,\1/' |
join -t, -o 1.2,2.2,2.3 -a 1 -a 2 -e 'no-match' - <(sort file1.txt)

如果进程替换不可用,只需原位排序file1.txt

sort -o file1.txt file1.txt

然后使用file1.txt 代替&lt;(sort file1.txt)


我认为该评论可能要求输入以下内容:

file1.txt

919167,hutch,mumbai
919594,idea,mumbai
902130,airtel,karnataka

file2.txt

919167000000
919594000000
919342313242

输出

no-match,airtel,karnataka
919167000000,hutch,mumbai
919342313242,no-match,no-match
919594000000,idea,mumbai

如果这不是评论的内容,请通过编辑问题来澄清,以添加额外的数据并以比 cmets 允许的更易读的格式输出。


使用扩展数据,这个稍微修改过的命令:

sort file2.txt |
sed 's/^\([0-9]\{6\}\)/\1,\1/' |
join -t, -o 1.2,2.2,2.3 -a 1 -e 'no-match' - <(sort file1.txt)

产生输出:

919167838888,hutch,mumbai
919212334323,no-match,no-match
919594998484,idea,mumbai

它看起来很像所需输出的排序版本。 -a n 选项控制是否打印来自文件 1 或文件 2(或两者)的不匹配记录; -e 选项控制为不匹配字段打印的值。当然,所有这些都可以从join 的手册页中轻松获得。

【讨论】:

  • 我认为它有效,但有一个变化,pradeep@pradeep-Vostro-1014:~$ sort file2.txt | sed 's/^([0-9]\{6\})/\1,\1/' | join -t, -o 1.2,2.2,2.3 -a 1 -a 2 -e 'no-match' - file1.txt 919167838888,hutch,mumbai 919594998484,idea,mumbai no-match,airtel,karnataka-- > 对于这个期望的输出应该是 919342313242,no-match,no-match。这可能吗?
  • 我无法确定 919342313242 数字的来源,或者数据文件的确切外观。请编辑问题(您可以在其中合理地格式化信息)以在输入文件中包含额外的数据行以及所需的输出。
  • 谢谢。上面带有 Join 的命令正在运行 fyn。我能在电话号码的海量数据上运行吗……比如数百万个号码:)。
  • 是的;我希望它能正常工作。如果大量数据存在问题,则将在排序操作中,而不是join
【解决方案2】:

这是使用GNU awk 的一种方式。运行如下:

awk -f script.awk file2.txt file1.txt

script.awk的内容:

BEGIN {
    FS=OFS=","
}

FNR==NR {
    sub(/[ \t]+$/, "")
    line = substr($0, 0, 6)
    array[line]=$0
    next
}

{
    printf ($1 in array) ? $0"\n" : "FILE1 no match --> "$0"\n"
    dup[$1]++
}

END {
    for (i in array) {
        if (!(i in dup)) {
            printf "FILE2 no match --> %s\n", array[i]
        }
    }
}

或者,这里是单行:

awk 'BEGIN { FS=OFS="," } FNR==NR { sub(/[ \t]+$/, ""); line = substr($0, 0, 6); array[line]=$0; next } { printf ($1 in array) ? $0"\n" : "FILE1 no match --> "$0"\n"; dup[$1]++} END { for (i in array) if (!(i in dup)) printf "FILE2 no match --> %s\n", array[i] }' file2.txt file1.txt

【讨论】:

  • 我将在接下来的 6-12 小时内添加对不匹配内容的支持
【解决方案3】:
awk -F, 'FNR==NR{a[$1]=$2","$3;next}{for(i in a){if($1~/i/) print $1","a[i]}}' your_file

【讨论】:

  • 嗨,sarathi,我有两个文件作为输入。
  • @Jonathan,谢谢。根据您的上述评论,我使用了 sed 和 join 的组合,它对我来说效果很好。我很高兴现在避免对此类事情进行数据库访问。谢谢你们。还有很多东西要学……期待更多。
猜你喜欢
  • 2016-07-30
  • 2020-04-16
  • 1970-01-01
  • 2021-06-15
  • 2020-12-13
  • 2017-07-30
  • 1970-01-01
  • 2020-10-05
  • 1970-01-01
相关资源
最近更新 更多