匹配 SED 范围匹配之前的日期模式,并在输出中包含匹配范围

匹配 SED 范围匹配之前的日期模式,并在输出中包含匹配范围

尝试使用多个值设置变量(例如:str_pattern),然后使用sed命令中的值将范围反向匹配到上一个空行或返回到 时遇到问题ExecuteThread

  • 示例脚本片段
    str_pattern="String1
    String2"
    
    tac $file | sed -n '/'"$str_pattern"'/,/^$/p' | tac
    
  • 输入文件示例
2023-01-01 01:00:00
    --blank line --
     ExecuteThread: #100 Exception in thread "main" java.lang.RuntimeException: 
     at com.stackify.stacktrace.StackTraceExample.methodB(StackTraceExample.java:13)  
     at com.stackify.stacktrace.something
     
     ExecuteThread: #101 Exception in thread "main" java.lang.RuntimeException: 
     at com.stackify.stacktrace.StackTraceExample.methodB(StackTraceExample.java:13)  
     at com.stackify.stacktrace.String1.line1   
     at com.stackify.stacktrace.String1.line2  
     at com.stackify.stacktrace.StackTraceExample.methodA(StackTraceExample.java:9)
      
     --blank line --
2023-01-01 02:00:00
    ExecuteThread: #100 Exception in thread "main" java.lang.RuntimeException: 
     at com.stackify.stacktrace.StackTraceExample.methodB(StackTraceExample.java:13)  
     at com.stackify.stacktrace.something

     ExecuteThread: #102 Exception in thread "main" java.lang.RuntimeException: 
     at com.stackify.stacktrace.StackTraceExample.methodB(StackTraceExample.java:13)  
     at com.stackify.stacktrace.String2.line1   
     at com.stackify.stacktrace.String2.line2  
     at com.stackify.stacktrace.StackTraceExample.methodA(StackTraceExample.java:9)
      
     --blank line --
  • 所需输出
2023-01-01 01:00:00
    ExecuteThread: #101 Exception in thread "main" java.lang.RuntimeException: 
         at com.stackify.stacktrace.String1.line1   
         at com.stackify.stacktrace.String1.line2  
2023-01-01 02:00:00    
    ExecuteThread: #102 Exception in thread "main" java.lang.RuntimeException: 
         at com.stackify.stacktrace.String2.line1   
         at com.stackify.stacktrace.String2.line2 

答案1

我会使用 perl 来实现这一点,因为它有一个选项 ( -00) 用于处理段落中的输入(由一个或多个空行分隔)和良好的多行字符串处理。

Perl 的-n选项使其工作方式类似于sed -n(读取并处理输入,而不自动打印每个输入行)......并sed -p使其工作方式类似于sed(读取、处理并自动打印输入)

$ perl -00 -n -e '
    if (/String1|String2/) {
      s/^.*StackTraceExample.*$//mg;
      s/\n\n/\n/g;
      print;
    }' input.txt 
 ExecuteThread: #101 Exception in thread "main" java.lang.RuntimeException:
 at com.stackify.stacktrace.String1.line1
 at com.stackify.stacktrace.String1.line2

 ExecuteThread: #101 Exception in thread "main" java.lang.RuntimeException:
 at com.stackify.stacktrace.String2.line1
 at com.stackify.stacktrace.String2.line2

用英语讲:

如果当前段落包含 String1 或 String 2,则删除包含 StackTraceExample(如果有)的所有行,然后删除删除 StackTraceExample 行后可能剩余的任何多余换行符,然后打印修改后的段落。

如果您需要从 sh 或 bash 脚本将 String1、String2、... StringN 传递给 perl,一种方法是通过环境中的导出变量传递它们:

#!/bin/sh

str_pattern="String1|String2"
excl_pattern="StackTraceExample"
export str_pattern excl_pattern

perl -00 -n -e '
  if (/$ENV{str_pattern}/) {
    s/^.*(?:$ENV{excl_pattern}).*$//mg;
    s/\n\n/\n/g;
    print
  }' input.txt 
 ExecuteThread: #101 Exception in thread "main" java.lang.RuntimeException:
 at com.stackify.stacktrace.String1.line1
 at com.stackify.stacktrace.String1.line2

 ExecuteThread: #101 Exception in thread "main" java.lang.RuntimeException:
 at com.stackify.stacktrace.String2.line1
 at com.stackify.stacktrace.String2.line2

str_pattern和中的值excl_pattern将被解释为 perl 正则表达式,而不是固定字符串,因此转义任何您想要视为文字的特殊字符。

%ENV是 Perl 中的哈希(关联数组),它提供对环境变量的访问。

注意:不幸的是,bash 数组无法有效导出(export不会返回错误代码,但它们在外部程序的环境中不可用 - 例如尝试export foo=(1 2 3); declare -p foo ; env | grep ^foo=在 bash 中运行,并且foo会出现在declare的输出中,但不会inenv的输出),因此变量必须是标量字符串。

答案2

使用(以前称为 Perl_6)

您可以使用fffRaku 版本的 sed“触发器”运算符

下面在以 开头的行上开始捕获\s* ExecuteThread,并在空白行上结束捕获[^^ $$]*.chars == 0也可以)。测试所需的字符串“String1”和“String2”(字面意思):

~$ raku -ne 'if m/   [^^ \s* ExecuteThread ] / fff / [^^ $$ ] / { .put if \
                m/ | [^^ \s* ExecuteThread ] 
                   | String1 
                   | String2 
                   | [^^ $$ ] / };'  file

清理一下,所需的字符串String1可以String2抽象为一个regex名为的类变量desired

~$ raku -ne 'my regex desired { String1 | String2 };  \
             if m/   [^^ \s* ExecuteThread ] / fff / [^^ $$ ] / { .put if \
                m/ | [^^ \s* ExecuteThread ] 
                   | <desired>
                   | [^^ $$ ] / };'  file

start此外,同样的抽象技巧还可以通过声明和stop正则表达式类变量使代码变得有点干燥。所以我们来到这个版本:

~$ raku -ne 'my regex start   { ^^ \s* ExecuteThread };  \
             my regex stop    { ^^ $$ };                 \
             my regex desired { String1  |  String2  };  \
             if (m/ <start> / fff / <stop> /) { 
                .put if m/ <start> | <desired> | <stop> / };'  file

请注意,在初始fff分组/选择之后,更简单的方法可能是去除输出中不需要的行,例如,最后一个子句{.put unless m/StackTraceExample/}

输入示例:

--blank line --

 ExecuteThread: #101 Exception in thread "main" java.lang.RuntimeException: 
 at com.stackify.stacktrace.StackTraceExample.methodB(StackTraceExample.java:13)  
 at com.stackify.stacktrace.String1.line1   
 at com.stackify.stacktrace.String1.line2  
 at com.stackify.stacktrace.StackTraceExample.methodA(StackTraceExample.java:9)

 --blank line --

 ExecuteThread: #101 Exception in thread "main" java.lang.RuntimeException: 
 at com.stackify.stacktrace.StackTraceExample.methodB(StackTraceExample.java:13)  
 at com.stackify.stacktrace.String2.line1   
 at com.stackify.stacktrace.String2.line2  
 at com.stackify.stacktrace.StackTraceExample.methodA(StackTraceExample.java:9)

 --blank line --

示例输出(上面的所有代码示例):

 ExecuteThread: #101 Exception in thread "main" java.lang.RuntimeException: 
 at com.stackify.stacktrace.String1.line1   
 at com.stackify.stacktrace.String1.line2  

 ExecuteThread: #101 Exception in thread "main" java.lang.RuntimeException: 
 at com.stackify.stacktrace.String2.line1   
 at com.stackify.stacktrace.String2.line2  

https://docs.raku.org/language/regexes
https://raku.org

相关内容