【问题标题】:How do I grep a string on multiple files only if the string is present in all of all the files?仅当所有文件中都存在字符串时,如何在多个文件上 grep 字符串?
【发布时间】:2020-12-26 13:29:25
【问题描述】:

我有大约 20 个文件。每个文件的第一列包含 ID(ID0001、ID0056、ID0165 等)。我有一个包含所有可能 id 的列表文件。我想从该文件中找到所有文件中都存在的 id。有没有办法为此使用grep?到目前为止,如果我使用命令:

grep "id_name" file*.txt,

即使它只存在于 1 个文件中,它也会打印 id。

【问题讨论】:

  • 如果您 edit 您的问题包括 minimal reproducible example,其中包含涵盖您所有用例的简洁、可测试的真正具有代表性的示例输入和预期输出,那么我们可以为您提供最好的帮助。请记住,从某些特定样本输入中产生您期望的输出的答案是获得解决方案的起点,而不是终点,因为还必须考虑稳健性、效率、清晰度、可移植性等。

标签: linux file grep


【解决方案1】:

有一个简单的grep管道可以做,但是写下来有点麻烦:

cut -f1 file1 | grep -Ff - file2  | grep -Ff - file3  | grep -Ff - file3  ...

另一种方法是使用 awk:

awk '{a[$1]++}END{for(i in a) if (a[i]==ARGC-1) print i}' file1 file2 file3 ...

后者假定每个文件的 id 都是唯一的。

如果它们不是唯一的,那就有点棘手了:

awk '(FNR==1){delete b}!($1 in b){a[$1]++;b[$1]}END{for(i in a) if (a[i]==ARGC-1) print i }' file1 file2 file3 ...

【讨论】:

    【解决方案2】:

    假设你有一个文件 ids_list.txt 中所有 id 的列表,每个 ID 都在一行中

     id001
     id101
     id201
      ...
    

    您要从中搜索的所有文件都在文件夹 data 中。所以在这种情况下,这个小脚本应该可以帮到你

    #!/bin/bash
    all_ids="";
    for i in `cat ids_list.txt`; do
        all_ids="$all_ids|$i"
    done
    all_ids=`echo $all_ids|sed -e 's/^|//'`
    grep -Pir "^($all_ids)[\s,]+" data
    

    它的输出会是这样的

    data/f1:id001, ssd
    data/f3:id201, some data
    ...
    

    【讨论】:

    • 如果您将其复制/粘贴到shellcheck.net,它会告诉您其中的一些问题。
    • @EdMorton 基本上脚本工作正常。 shelcheck.net 建议使用括号而不是反引号和 while 循环而不是 for 循环。用括号替换反引号根本没有问题,但是如果我们使用 while 循环而不是 for 循环,那么变量范围问题将在 while 循环在其自己的子 shell 中运行时出现。
    • 它至少还必须警告您缺少引号。写一个需要子shell的while循环-不,如果正确编写(即不从管道读取)则不会。尝试while read i; do all_ids="$all_ids|$i"; done < ids_list.txt 并查看mywiki.wooledge.org/BashFAQ/001 了解详情。另请参阅why-is-using-a-shell-loop-to-process-text-considered-bad-practice,了解为什么不为此使用 shell 读取循环。
    【解决方案3】:

    这可能是您想要做的,但没有样本输入/输出,这是一个未经测试的猜测:

    awk '
        !seen[FILENAME,$1]++ {
            cnt[$1]++
        }
        END {
            for (id in cnt) {
                if ( cnt[id] == (ARGC-1) ) {
                    print id
                }
            }
        }
    ' list file*
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-07-06
      • 2014-10-29
      • 1970-01-01
      • 2022-01-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多