AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • 主页
  • 系统&网络
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • 主页
  • 系统&网络
    • 最新
    • 热门
    • 标签
  • Ubuntu
    • 最新
    • 热门
    • 标签
  • Unix
    • 最新
    • 标签
  • DBA
    • 最新
    • 标签
  • Computer
    • 最新
    • 标签
  • Coding
    • 最新
    • 标签
主页 / coding / 问题 / 79578428
Accepted
Ramanan T
Ramanan T
Asked: 2025-04-17 11:29:00 +0800 CST2025-04-17 11:29:00 +0800 CST 2025-04-17 11:29:00 +0800 CST

打印文件中匹配的模式以及匹配的行

  • 772

在一个复杂的脚本中,我使用grep模式文件来获取匹配的行

例如:这是包含文本的文件

$ cat file.txt
abc$(SEQ)asdasd
wwww$(SEQ)asqqqqqq
efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz
klmn$(SEQ)11111111
op$(SEQ)44444444
qrs$(SEQ)777
tuv$(SEQ)mmmmmmmmm
qrs$(SEQ)777444
asdsd777hdhfgjdfasd
wxyzfhdfghdfh

这是模式文件

$ cat pattren.txt
444
777
asd

我正在使用以下grep命令来获取匹配的行

这

在命令行中,我可以看到匹配的模式,但在日志中却看不到。所以我需要一种方法来打印匹配的行和匹配的模式。输出应该类似于:在 TAB 键(或任何可识别的格式)后打印模式。

abc$(SEQ)asdasd <TAB> asd
efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz  <TAB> asd
op$(SEQ)44444444    <TAB>   444
qrs$(SEQ)777    <TAB>   444
qrs$(SEQ)777444  <TAB>  777444
asdsd777hdhfgjdfasd  <TAB>  asd777 

我可以使用 grep-o但无法将两者(即有和无-o)结合在一起。

没有必要使用grep,我很乐意使用任何其他可以完成此操作的命令。

string
  • 3 3 个回答
  • 58 Views

3 个回答

  • Voted
  1. Best Answer
    markp-fuso
    2025-04-17T12:17:02+08:002025-04-17T12:17:02+08:00

    一个awk想法:

    awk '
    BEGIN   { sep1 = "\t"; sep2 = "," }                       # predefine our separators; modify as desired
    
    FNR==NR { ptns[$0]; next }                                # 1st file: save each line as a new index in our ptns[] array
    
            { sfx = ""                                        # 2nd file: reset our suffix
    
              for (ptn in ptns)                               # loop through the indices (aka patterns) of the ptns[] array
                  if (index($0,ptn))                          # if the pattern exists in the current line (ie, index() returns a value > 0) then ...
                     sfx = sfx (sfx == "" ? "" : sep2) ptn    # append the pattern to our suffix
    
              if (sfx != "")                                  # if the suffix is not blank then we found at least one match so ...
                 print $0 sep1 sfx                            # print current line and append the suffix
            }
    ' pattern.txt file.txt
    

    或者,将脚本主体放在awk文件中,然后通过以下方式访问awk -f ...:

    $ cat my_grep.awk
    BEGIN   { sep1 = "\t"; sep2 = "," }
    FNR==NR { ptns[$0]; next }
            { sfx = ""
              for (ptn in ptns)
                  if (index($0,ptn))
                     sfx = sfx (sfx == "" ? "" : sep2) ptn
              if (sfx != "")
                 print $0 sep1 sfx
            }
    
    $ awk -f my_grep.awk pattern.txt file.txt
    

    笔记:

    • 假设行中patterns.txt没有任何前导/尾随空格,否则会导致调用index()失败
    • (ptn in ptns)不保证模式的处理顺序,这意味着无法保证在行尾打印时所述模式的顺序;虽然可以添加额外的代码来满足排序要求,但 OP 需要提供更多细节以包括如何处理重复和/或重叠的模式(例如,a并且as会在同一index()位置匹配,因此哪种模式会被视为实际匹配?)
    • 因为index()只会找到模式的第一次出现,并且我们不会尝试匹配第一个匹配之后的匹配,所以这种方法只会告诉我们至少有一个4匹配;需要额外的编码来确定匹配的数量,但也需要 OP 提供有关如何处理重复和/或重叠模式的更多详细信息(例如,与44匹配多少次44444444?)

    两种方法都会产生:

    abc$(SEQ)asdasd asd
    efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz  asd
    op$(SEQ)44444444    444
    qrs$(SEQ)777    777
    qrs$(SEQ)777444 444,777
    asdsd777hdhfgjdfasd asd,777
    
    • 5
  2. phuclv
    2025-04-17T14:55:15+08:002025-04-17T14:55:15+08:00

    由于允许任何可识别的格式,最简单的解决方案是将 grep 发出的 ANSI 序列直接替换为您想要的任何分隔符,例如制表符:

    $grep --color=always -f pattern.txt file.txt | \
      sed -E 's/(\x1b\[[0-9;]*[A-Za-z])+/\t/g'
    abc$(SEQ) asd asd
    efg hij$(SEQ) asd asd asd $(SEQ)zzzzzz
    操作$(SEQ) 444 444 44
    qrs$(SEQ) 777
    qrs$(序列) 777 444
        asd sd 777 hdhfgjdf asd
    

    也可以捕获开始和结束 ANSI 序列之间的每个匹配,例如这里我将每个匹配包装在[]

    $grep --color=always -f pattern.txt file.txt | \
      sed -E -e 's#\x1b\[m#]\t#g'  -e 's#\x1b\[[0-9;]+m#\t[#g'
    abc$(SEQ) [asd] [asd]
    efg hij$(SEQ) [asd] [asd] [asd] $(SEQ)zzzzzz
    操作$(SEQ) [444] [444] 44
    qrs$(SEQ) [777]
    qrs$(SEQ) [777] [444]
        [asd] sd [777] hdhfgjdf [asd]
    

    要在最后打印图案,你可以使用类似这样的方法

    $grep --color=always -f pattern.txt file.txt | while read -r line; do
        printf "%s\t=== Patterns: " "$line"
        echo "$line" | perl -nE 'while (/\x1b\[[0-9;]+m(.*?)\x1b\[m/g) {
            print "$1 "; }; print "\n";'
    done
    
    abc$(SEQ)asdasd === 模式:asd asd
    efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz === 模式:asd asd asd
    op$(SEQ)44444444 === 模式:444 444
    qrs$(SEQ)777 === 模式:777
    qrs$(SEQ)777444 === 模式:777 444
    asdsd777hdhfgjdfasd === 图案:asd 777 asd
    
    $grep --color=always -f pattern.txt file.txt | while read line; do \
        printf "$line\t=== Patterns: " | sed -E 's/\x1b\[[0-9;]*[A-Za-z]//g'
        echo "$line" | sed -E 's/^.*\x1b\[[0-9;]+m(.+)\x1b\[m/\1/g'
    done
    abc$(SEQ)asdasd === 模式:asd
    efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz === 模式:asd$(SEQ)zzzzzz
    op$(SEQ)44444444 === 模式:44444
    qrs$(SEQ)777 === 模式:777
    qrs$(SEQ)777444 === 模式:444
    asdsd777hdhfgjdfasd === 图案:asd
    

    如果你想保留颜色以供以后使用,你也可以直接这样做

    $ grep --color=always -f pattern.txt file.txt > output.txt
    $ cat output.txt
    
    • 1
  3. Timur Shtatland
    2025-04-18T02:23:02+08:002025-04-18T02:23:02+08:00

    要在 Perl 中执行此操作,请使用以下命令:

    perl -lne '
    BEGIN {
        chomp( @pats = `cat pattern.txt` );
        $pat = join "|", @pats;
    }
    if ( @matches = m{($pat)}g ) {
        %seen = ();
        @uniq = grep !$seen{$_}++, @matches;
        $uniq = join ",", @uniq;
        print "$_\t$uniq";
    }' file.txt
    

    输出:

    abc$(SEQ)asdasd      asd
    efg hij$(SEQ)asdasdasd$(SEQ)zzzzzz      asd
    op$(SEQ)44444444        444
    qrs$(SEQ)777    777
    qrs$(SEQ)777444 777,444
    asdsd777hdhfgjdfasd     asd,777
    

    Perl“单行命令”使用以下命令行标志::
    -e告诉 Perl 在行内查找代码,而不是在文件中。
    -n:一次循环输入一行,$_默认情况下将其分配给。 :在行内执行代码之前
    -l去除输入行分隔符(默认情况下在 *NIX 上),并在打印时附加它。"\n"

    正则表达式使用这个修饰符::
    g重复匹配模式。

    chomp( @pats = `cat pattern.txt` );
    

    上面这一行将文件内容读pattern.txt入数组@pats并删除换行符(chomp)。

    $pat = join "|", @pats;:将模式连接成一个字符串,用|(= OR运算符)分隔。
    @matches = m{($pat)}g:将模式重复匹配(m{...}g)从 读取的当前行file.txt。所有匹配都存储在数组中@matches(如果出现多次,则可能包含相同模式的重复)。
    if ( @matches = ... ):如果至少有一个匹配项,@matches则评估为。 :使匹配项唯一并将其存储在数组中。:用逗号连接唯一匹配项,并将结果存储在一个字符串中。TRUE
    @uniq = grep !$seen{$_}++, @matches;@uniq
    $uniq = join ",", @uniq;$uniq

    参见:

    • perldoc perlrun:如何执行 Perl 解释器:命令行开关
    • perldoc perlre:Perl 正则表达式(regexes)
    • perldoc perlrequick:Perl 正则表达式快速入门
    • 1

相关问题

  • 这个位置的“let”表达式是不稳定的

  • Rust 是否会隐藏未重新声明的变量?

  • 使用 REGEXMATCH 查找具有精确字符串长度的单元格,而不是具有共享单词和不同字符串的单元格

  • 需要将带有列表值的字符串转换为scala中的Map类型

  • pcase 无法识别字符串匹配

Sidebar

Stats

  • 问题 205573
  • 回答 270741
  • 最佳答案 135370
  • 用户 68524
  • 热门
  • 回答
  • Marko Smith

    重新格式化数字,在固定位置插入分隔符

    • 6 个回答
  • Marko Smith

    为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会?

    • 2 个回答
  • Marko Smith

    VScode 自动卸载扩展的问题(Material 主题)

    • 2 个回答
  • Marko Smith

    Vue 3:创建时出错“预期标识符但发现‘导入’”[重复]

    • 1 个回答
  • Marko Smith

    具有指定基础类型但没有枚举器的“枚举类”的用途是什么?

    • 1 个回答
  • Marko Smith

    如何修复未手动导入的模块的 MODULE_NOT_FOUND 错误?

    • 6 个回答
  • Marko Smith

    `(表达式,左值) = 右值` 在 C 或 C++ 中是有效的赋值吗?为什么有些编译器会接受/拒绝它?

    • 3 个回答
  • Marko Smith

    在 C++ 中,一个不执行任何操作的空程序需要 204KB 的堆,但在 C 中则不需要

    • 1 个回答
  • Marko Smith

    PowerBI 目前与 BigQuery 不兼容:Simba 驱动程序与 Windows 更新有关

    • 2 个回答
  • Marko Smith

    AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String”

    • 1 个回答
  • Martin Hope
    Fantastic Mr Fox msvc std::vector 实现中仅不接受可复制类型 2025-04-23 06:40:49 +0800 CST
  • Martin Hope
    Howard Hinnant 使用 chrono 查找下一个工作日 2025-04-21 08:30:25 +0800 CST
  • Martin Hope
    Fedor 构造函数的成员初始化程序可以包含另一个成员的初始化吗? 2025-04-15 01:01:44 +0800 CST
  • Martin Hope
    Petr Filipský 为什么 C++20 概念会导致循环约束错误,而老式的 SFINAE 不会? 2025-03-23 21:39:40 +0800 CST
  • Martin Hope
    Catskul C++20 是否进行了更改,允许从已知绑定数组“type(&)[N]”转换为未知绑定数组“type(&)[]”? 2025-03-04 06:57:53 +0800 CST
  • Martin Hope
    Stefan Pochmann 为什么 {2,3,10} 和 {x,3,10} (x=2) 的顺序不同? 2025-01-13 23:24:07 +0800 CST
  • Martin Hope
    Chad Feller 在 5.2 版中,bash 条件语句中的 [[ .. ]] 中的分号现在是可选的吗? 2024-10-21 05:50:33 +0800 CST
  • Martin Hope
    Wrench 为什么双破折号 (--) 会导致此 MariaDB 子句评估为 true? 2024-05-05 13:37:20 +0800 CST
  • Martin Hope
    Waket Zheng 为什么 `dict(id=1, **{'id': 2})` 有时会引发 `KeyError: 'id'` 而不是 TypeError? 2024-05-04 14:19:19 +0800 CST
  • Martin Hope
    user924 AdMob:MobileAds.initialize() - 对于某些设备,“java.lang.Integer 无法转换为 java.lang.String” 2024-03-20 03:12:31 +0800 CST

热门标签

python javascript c++ c# java typescript sql reactjs html

Explore

  • 主页
  • 问题
    • 最新
    • 热门
  • 标签
  • 帮助

Footer

AskOverflow.Dev

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve