尝试使用多个值设置变量(例如: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)
您可以使用fff
Raku 版本的 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