我有一个不断填充的日志文件;我们假设它的名称是logfile.txt。在此日志文件中,我想使用任何 bash 命令从包含同一行中其他字符串的单行中连续捕获子字符串。
这是日志文件中一行的示例:
2023-08-31 09:56:39,925 [G_M80T72|utx:0:ffffac17000b:45253299:64ec7753:79cb0e|chnl:LN1_CRYPTO_IN_MQ_REQ_AMP|id:196010175121000000000002134] WARN transaction.GeneralTransactionFailureException - GeneralTransactionFailureException Gateway.Transaction[196010175121000000000000067v1], StatusReason[ProcessingFailed/PayloadIntegrityCheckFailed]
我想在每次该行包含 时捕获 string1LN1
和 string2 。CRYPTO_IN_MQ_REQ_AMP
PayloadIntegrityCheckFailed
String1 前面始终带有chnl:
',而 string2 后面始终带有管道。这2个字符串总是用下划线分隔(但string2也可以包含下划线)在我的例子中string1=LN1但它可能像{任何字母字符}LN{任何数字} String2可以由字母和数字组成
捕获 string1 和 string2 后,我将在另一个命令中将它们用作参数,例如:
{another_command} string1 string2
当然,只有新的条目应该被捕获,我不想连续扫描完整的日志,只扫描新的行,所以我想首先是tail -f
文件,然后使用一些 sed 魔法和正则表达式。
您知道如何继续吗?
答案1
$ sed -e '/PayloadIntegrityCheckFailed/!d' -e 's/.*chnl:\([^|]*\).*/\1/' -e 's/_/ /' file
LN1 CRYPTO_IN_MQ_REQ_AMP
上面的命令sed
会丢弃所有不包含字符串的行PayloadIntegrityCheckFailed
。其余行将替换为chnl:
后面|
字符之间的任何内容。该字符串中的第一个下划线被空格字符替换,并输出结果。
第二个sed
表达式s/.*chnl:\([^|]*\).*/\1/
可能可以替换为两个更简单的替换,s/.*chnl://
and s/|.*//
(严格来说,这不是同一件事,但对存在子字符串chnl:
且后面跟着一个|
字符的示例数据具有相同的效果)。
sed
可以使用命令读取输出,而不是文件tail -f
,以进行连续操作。在这种情况下,如果可能的话,您可能还想使用行缓冲操作sed
(非标准-u
选项)。
tail -f /var/log/some.log | sed -u -e ...as before...
要将这些字符串读入变量并在其他进程中使用它们,您可以循环读取上述管道的输出while
:
tail -f ... | sed ... |
while read -r first_string second_string; do
some-command "$first_string" "$second_string"
done
答案2
有多种方法可以解决您的问题,每种方法都使用不同的工具:cat、grep、awk 等,...
鉴于您的陈述“我想连续捕获子字符串”,我想正确的方法是用于tail -f
在屏幕上显示匹配项或将它们写入文件。
要将它们打印在屏幕上:
tail -f /path/to/your/file.log | grep "PayloadIntegrityCheckFailed" | grep -E "LN1.*CRYPTO_IN_MQ_REQ_AMP"
要将结果保存到文件中:
tail -f /path/to/your/file.log | grep "PayloadIntegrityCheckFailed" | grep -E "LN1.*CRYPTO_IN_MQ_REQ_AMP" >> /tmp/some_file.txt
解释:
tail -f
不断输出实时添加到 file.log 中的新行。grep "PayloadIntegrityCheckFailed"
过滤那些新行并忽略不包含该PayloadIntegrityCheckFailed
字符串的行- grep -E 将 grep 置于 REGEXP 模式
- 搜索模式
"LN1.*CRYPTO_IN_MQ_REQ_AMP"
会抓取包含该字符串的任何行LN1
以及CRYPTO_IN_MQ_REQ_AMP
该行中更前面的其他位置。
在您的示例中,字符串似乎是由“_”字符LN1
连接起来的。CRYPTO_IN_MQ_REQ_AMP
尽管如此,由于您没有在问题中明确说明,我已用“.*”任意数量的字符分隔两个字符串。