gpt4 book ai didi

regex - 如何处理每个结果 - 而不是 grep (oz) 命令的行(早于 2.25)

转载 作者:太空狗 更新时间:2023-10-29 12:25:34 24 4
gpt4 key购买 nike

从版本 2.25 开始,一个 "bug" in grep是固定的,因此使用空字节而不是换行符来终止输出行。这对于捕获和处理多行 grep 匹配来说非常简单(参见示例)

不幸的是,我在生产环境中遇到了 grep 版本 2.20。这意味着对于处理\n 终止的日志文件,您无法将 grep 匹配与每一行输出区分开来。

因此我的问题:

当您遇到 2.25 之前的版本时,处理每个结果的最有效方法是什么 - 而不是 grep (oz) 命令的行?

(注意:这是一个更复杂的脚本的小例子,需要根据请求处理超过 10k 的大日志文件,因此我寻求“最有效”的解决方案)

一个简单的例子:

测试日志

flag test1
flag test2
flag test3
test4
test5
flag test6

test7

flag test8

测试.sh

#!/bin/bash
#regex explained:
#(?s)enable multiline pattern search
#(flag) capturegroup with pattern indicating new entry
#[[:blank:]] followed by a space
#(.*?) capturegroup for the rest of the entry, non-greedy
#(?=(?:\r\n|[\r\n])(flag)|\z) positive lookahead:
# - stop when the next newline begins with flag
# - OR if last entry is a match: proceed 'till end of entry

regex_multiline="(?s)(flag)[[:blank:]](.*?)(?=(?:\r\n|[\r\n])(flag)|\z)"
logfile="./test.log"

test1(){
#this works only with grep 2.25 or higher,
#which returns a NULL-byte delimiter after each capture
echo start
while IFS= read -r -d '' line ; do
printf '<test>%s</test>\n' "$line"
done < <(grep -Pzo $regex_multiline $logfile)
echo end
}

test2(){
#I need this to work for each match, instead of each line
echo start
while IFS= read -r line ; do
printf '<test>%s</test>\n' "$line"
done < <(grep -Pzo $regex_multiline $logfile)
echo end
}

测试 1 结果是我想要的:

start
<test>flag test1</test>
<test>flag test2</test>
<test>flag test3
test4
test5</test>
<test>flag test6

test7
</test>
<test>flag test8</test>
end

测试 2 结果在

start
<test>flag test1</test>
<test>flag test2</test>
<test>flag test3</test>
<test> test4</test>
<test> test5</test>
<test>flag test6</test>
<test></test>
<test>test7</test>
<test> </test>
<test>flag test8</test>
end

最佳答案

我认为您最好在这里使用 perl 而不是 grep。您可以使用几乎不修改的正则表达式1,只需将其替换为\1\x002:

regex_multiline="(?s)(flag[[:blank:]].*?)(?=(?:\r\n|[\r\n])flag|\z)"
perl -0777 -pe "s/$regex_multiline/\1\x00/g" < "$logfile"

1您的正则表达式有点奇怪,捕获组在您的 grep 命令的上下文中没有执行任何操作(例如 (flag))。我只是把你要匹配的整个部分放在一组,这样它就对应于替换部分中的\1。根据需要进行调整/我遗漏了一些东西。

2使用 \1\0(对于“匹配组一”、“空字节”)实际上也有效,但这似乎有点令人困惑。

关于regex - 如何处理每个结果 - 而不是 grep (oz) 命令的行(早于 2.25),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42065453/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com