从日志文件中提取 2 个字符串

从日志文件中提取 2 个字符串

我有一个不断填充的日志文件;我们假设它的名称是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_AMPPayloadIntegrityCheckFailed

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尽管如此,由于您没有在问题中明确说明,我已用“.*”任意数量的字符分隔两个字符串。

相关内容