如何打印正则表达式匹配的一部分以及所有其他匹配的列表

如何打印正则表达式匹配的一部分以及所有其他匹配的列表

我正在总结一些测试结果,所以我有这种类型的文本:

FAILED src/path/to/code.test.js
  Test Suite
    

答案1

这更像是一项工作perl

perl -lne '
  if (/^\h*at\h.*?\((src.*?\.test\.js):(\d+:\d+)\)/) {
    $total{$1}++;
    $lines{$1}->{$2}++
  }
  END {
    for $file (sort {$total{$b} <=> $total{$a}} keys %total) {
      my $l = $lines{$file};
      print "$total{$file} $file (" . 
      join(", ", map "$l->{$_} - $_", sort {$l->{$b} <=> $l->{$a}} keys %$l) . ")"
    }
  }'

请注意,*?由于 的非贪婪版本*是 perl 正则表达式运算符。我知道只有一种sed实现支持它(除了-r非标准的等效项之外-E),但我怀疑这就是您正在使用的实现。这就是 ast-open,sed据我所知,默认情况下任何系统都不会提供这种工具,甚至包括已知包含或至少考虑包含 ksh93 以外的 ast-open 工具的 Illumos 也不包含在内。在sed(引入该选项的那个-r)的 GNU 实现中, .*?is ?(0 或 1 个前面的原子) 应用于(0 个或多个字符),因此与and (0 或 1 个或多个字符).*相同也一样。.*.+?.*

答案2

awk '/^[[:blank:]]*at.*\(src.*\.test\.js:[0-9]+:[0-9]+\)/{
    split($0, tmp, /[)(:]/) ## Assuming there is no ), ( and : in the filePath
    fileCnt [tmp[2]]++
    fileErrs[tmp[2], tmp[3]":"tmp[4]]++
}

END{
    for (fileName in fileCnt){
        sep=""
        printf ("%s %s (", fileCnt[fileName], fileName)
        for(file in fileErrs){
            split(file, tmp, SUBSEP)
            if(fileName==tmp[1]){
                printf("%s - %s", sep fileErrs[file], tmp[2])
                sep=", "
            }
        }
        print ")"
    }
}' infile   ## or infiles*

关联的数组fileCnt仅保留文件名的计数;数组的键是文件的名称,值是它们看到的次数。关联的
数组fileErrs保存每个文件名的错误计数;其中键是 fileName+errNums 的组合。

在 END 块,我们正在处理文件数数组并打印文件计数fileCnt[fileName],然后打印文件名本身fileName;然后我们正在处理文件错误数组并分割关键部分,然后我们将第一部分与文件名进行比较,以查找每个文件的单独错误。

答案3

使用(以前称为 Perl_6)

~$ raku -ne 'state %h; state $i; ++$i;  \
             if m/ ^ \h* at \h .*?  "(" ~ ")" [(src .*? \.test \.js) \: (\d+ \: \d+)] /   \
             -> { %h.push: $0 => $i ~"|"~ $1 }; END .say for %h;'  file

-ne简而言之,代码使用(非自动打印)命令行标志在输入文件上逐行运行。给出了一个哈希值%h$i声明了一个迭代器。对于每一行,$i迭代器都会递增。if与正则表达式匹配的条件测试相似但不相同到 @Stephane_Chazelas 发布的 Perl5 代码。然而,这个 Raku 正则表达式使用了一个很好的(较新的)功能——Raku 的~嵌套数据结构波浪线语法:"(" ~ ")" [ … ]。 Raku 正则表达式将捕获路径$0并将冒号分隔的数字捕获到$1

当找到(逐行)匹配时,它会被push添加到%h散列中:($0路径)用作键,而值则成为使用代码(使用~)连接到捕获的数字部分的行号: 。由于散列中不能存在重复的键,因此每个键(即路径)会累积不同的值。在读取行的最后,输出哈希值。$1$i ~"\t"~ $1END%h

输入示例:

#See above. OP's original file was concatenated 5 times, 
#one record was altered (path and digits).

输出示例 (1):

src/path/to/code.test.js => [13|31:415 27|31:415 55|31:415 69|31:415]
src/path/to/othercode.test.js => 41|32:416

要获取计数的前导列,请将后面的代码替换END为以下内容:

for %h.kv -> $k,$v {say $v.elems, "\t", $k => $v};

输出示例 (2):

4   src/path/to/code.test.js => [13|31:415 27|31:415 55|31:415 69|31:415]
1   src/path/to/othercode.test.js => 41|32:416

[注意:在涉及哈希值的情况下,通常say会生成箭头分隔的输出。在上面,您只需将最终命令更改为]key => value即可获得制表符分隔的键值输出。sayput

https://docs.raku.org/language/regexes#Tilde_for_nesting_structs
https://docs.raku.org/language/hashmap
https://raku.org

相关内容