【问题标题】:Search multiple strings from file in multiple files in specific column and output the count in unix shell scripting在特定列的多个文件中从文件中搜索多个字符串,并在 unix shell 脚本中输出计数
【发布时间】:2026-02-25 11:30:01
【问题描述】:

我在互联网上对此进行了广泛搜索,但没有找到太多细节。

问题描述:

我正在使用 aix 服务器。

我有一个 pattern.txt 文件,其中包含 100 个客户的 customer_id,格式如下:

160471231

765082023

75635713

797649756

8011688321

803056646

我有一个目录(/home/aswin/temp),其中包含多个用竖线(|)分隔的文件(1.txt、2.txt、3.txt 等)。样本格式:

797649756|1001|123270361|797649756|O|2017-09-04 23:59:59|10|123769473 803056646|1001|123345418|1237330|O|1999-02-13 00:00:00|4|1235092 64600123|1001|123885297|1239127|O|2001-08-19 00:00:00|10|1233872 75635713|1001|123644701|75635713|C|2006-11-30 00:00:00|11|12355753 424346821|1001|123471924|12329388|O|1988-05-04 00:00:00|15|123351096 427253285|1001|123179704|12358099|C|2012-05-10 18:00:00|7|12352893

我需要做什么从目录中所有文件的所有文件中搜索 pattern.txt 文件中的所有字符串,在每个文件的第一列中,并列出每个文件名和匹配数。因此,如果同一行有超过 1 个匹配项,则应计为 1 个。

所以输出应该是这样的(只计算第一列中的匹配项):

1.txt:4

2.txt:3

3.txt:2

4.txt:5

到目前为止我做了什么:

cd /home/aswin/temp

grep -srcFf ./pattern.txt * /dev/null >> logfile.txt

这是以所需格式提供输出,但它会搜索所有列中的字符串,而不仅仅是第一列。所以输出数量比预期的要多得多。

请帮忙。

【问题讨论】:

    标签: string shell lookup


    【解决方案1】:

    如果你想用 grep 做到这一点,你必须改变模式。

    使用您的命令,您在 /dev/null 中搜索模式,输出为 /dev/null:0

    我认为你想要 2>/dev/null 但这不是必需的,因为你告诉 -s 到 grep。

    您的模式文件位于同一目录中,因此 grep 在其中搜索并输出 pattern.txt:6

    您的所有文件都在同一个目录中,因此不需要 -r。

    你把日志文件放在同一个目录下,所以第二次在里面运行命令 grep search 并输出 logfile.txt:0

    如果您可以修改模式文件,则将每一行写成 ^765082023| 你重命名这个文件而不带 .txt

    所以这个命令给你你要找的东西。

    grep -scf pattern *.txt >>logfile
    

    如果不能修改pattern文件,可以使用awk。

    awk -F'|' '
    NR==FNR{a[$0];next}
    FILENAME=="pattern.txt"{next}
    $1 in a {b[FILENAME]++}
    END{for(i in b){print i,":",b[i]}}
    ' pattern.txt *.txt >>logfile.txt
    

    【讨论】:

    • 感谢 ctac 的建议。如果我不使用 /dev/null,如果目录只有 1 个文件,则输出不包含文件名和计数。 1. 修改模式文件,运行如下命令。 grep -srcFf pattern1.txt * /dev/null >> logfile.txt 结果是 0 匹配。 2. awk 解决方案有效。但现在我面临另一种情况。假设模式文件包含一个字符串 7650820。如果目标文件在第一列中有 7650820、76508201、76508202、76508203,它会给我 4 个匹配项。它应该完全匹配并输出为 1。请提出修改建议。
    • @Aswin 1)我告诉你修改模式文件并将其命名为不带 .txt 的模式 2)你的模式文件现在是一个正则表达式,你不必在 grep 中使用 -F。3)你可以使用 -H 代替 /dev/null 所以命令变成 grep -scHf pattern *.txt >> logfile.4) 我不能用 awk 重现你的问题,如果数组 a 的元素在搜索中的 $1 行有名字$1,所以如果a中的名字是7650820,$1=76508201,就不一样了,指令b[FILENAME]++没有被执行。
    • 我的错误。源文件本身有重复。现在两个建议的解决方案都有效。非常感谢。
    • 感谢 ctac。我应用了 awk 解决方案,它工作了一段时间,但现在我面临另一种情况。 *.txt 文件可以有多行出现相同的模式。因此,如果模式文件有 5 个模式,则每个文件的输出匹配数都会达到 50 或 70 之类的大数字。我们能否修改这个特定的 awk 解决方案,以仅计算目标文件中每个模式的一次出现次数,以便每个文件的匹配项不超过模式文件中的模式总数。