【问题标题】:Match multiple patterns in multiple files匹配多个文件中的多个模式
【发布时间】:2022-01-07 11:26:31
【问题描述】:

我想在具有相同扩展名的多个文件中匹配/检查多个模式pattern1pattern2...文件,它返回false。 示例:

file1.ext

this file has pattern1
with many other lines

file2.ext

this file has pattern2
with many other lines

在这种情况下,由于 pattern1 和 pattern2 都存在(尽管在不同的文件中),它应该返回 true。也就是说,所有模式都必须存在于文件中。

我们可以做到这一点的一种方法是使用 grep 在所有文件中单独搜索每个模式,并检查每个 grep 是否返回至少 1 个匹配项。
grep -R 'pattern1' --include="*.ext"
grep -R 'pattern2' --include="*.ext"
...
但这会很昂贵,因为可能需要搜索大量文件和多种模式。 另一种方法是grep 为所有带有| 的模式并解析输出以检查是否找到了所有模式。
grep -oR 'pattern1\|pattern2' --include="*.ext"

输出:

file2.ext:pattern2
file1.ext:pattern1

PS:在文件中搜索模式是我正在编写的 python 脚本的要求之一。

编辑:关于这里模式的含义的一些上下文。
模式是一个字符串。它可能包含特殊字符。 即使pattern 是一行中的子字符串,也应该发生匹配。更好的模式示例:

文件:

move-result-object v0
invoke-virtual {v0, v2}, Landroid/content/Intent;->hasExtra(Ljava/lang/String;)Z
move-result v3
const/4 v4, 0x0
if-nez v3, :cond_0

图案:

Landroid/content/Intent;->hasExtra

【问题讨论】:

  • 很抱歉给您带来了困惑。这是第二个,即所有模式都必须存在于文件中。编辑了帖子。
  • 我更新了我的答案。我看到您在其中一个答案 (stackoverflow.com/questions/70174585/…) 下的评论中要求提供其他功能。请将您的所有要求放在您的问题中,不要在 cmets 中添加任何无法格式化和可能遗漏的内容。

标签: python awk sed grep


【解决方案1】:

听起来可能是你想要的(未经测试):

awk '
    BEGIN { OFS=":" }
    NR==FNR {
        tgts[$0]
        next
    }
    {
        for ( tgt in tgts ) {
            if ( index($0,tgt) ) {
                print FILENAME, tgt
                delete tgts[tgt]
                if ( length(tgts) == 0 ) {
                    allFound = 1
                    exit
                }
            }
        }
    }
    END {
        exit !allFound
    }
' targets *.ext

以上假设:

  1. 您有一个支持 length(array) 的 awk 版本(大多数都支持)。
  2. 您有一个名为 targets 的文件,其中列出了您要查找的所有“模式”,每一个都在自己的行中。
  3. “返回真/假”是指“以成功/失败退出状态退出”。

【讨论】:

    【解决方案2】:

    使用 awk。但首先是模式文件:

    $ cat patterns
    pattern1
    pattern2
    

    然后是 awk:

    awk '
    NR==FNR {                     # process pattern file
        a[$0]                     # hash all patterns to a
        next
    }
    {                             # process the rest of the files
        for(i=1;i<=NF;i++)        # loop all strings
            if($i in a) {         # if string matches a string in pattern file
                print $i,FILENAME # print matched string and filename
                delete a[$i]      # remove it
            }
        for(j in a)               # continue while words strings left in a hash
            next
        exit ec=0                 # or exit once all are found
    }
    END {         
        if(ec=="")                # if we reach end without exiting
            exit 1                # not all strings were found
    }' patterns file1 file2
    

    “输出”:

    $ echo $?  # true/false as exit code: 0=all found, 1=not all found
    0           
    

    编辑:在添加print $1,FILENAME(和它周围的{}s)之后,它现在还会打印匹配的字符串和第一次匹配的文件。

    【讨论】:

    • 感谢您的回答。这似乎是我想要的东西。我们可以返回匹配的模式,而不是重新调整真/假吗?另外我们可以返回模式首先匹配的文件吗?
    • 添加了print 以打印匹配项和首次找到该匹配项的文件的名称。
    • 嘿,我已经编辑了这个问题。我假设上述命令仅适用于完全匹配。
    • 是的,只有完全匹配、用空格分隔的单词(制表符和换行符)以反映您提供的示例数据。请不要对问题进行重大更改。而是关闭这个并发布一个包含您新的完整要求的新问题。将不断变化的需求留给现实世界和工作......
    • @lightBullet 关于Instead of returning true/false, can we return the patterns which matched - 程序在 Unix 中不会“返回”任何内容,它们会打印输出并以状态退出。我认为您要求的是打印匹配的模式并以状态成功/失败退出,类似于grep的行为方式(除了它打印匹配的文本,而不是要匹配的字符串)。请更新您的问题以包含该要求。
    猜你喜欢
    • 1970-01-01
    • 2011-10-20
    • 2017-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多