- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
从版本 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\x00
2:
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/
我有一个 javascript 函数,可以执行以下操作; 它将日期编辑框设置为与另一个日期编辑相同的日期。但是我希望它将 txt_Testin
我有一个输入框,类型为“时间”。我想将迟到时间 (23:00pm) 作为最小值,将早期时间 (6:00am) 作为最大值 - 创建一个 23pm - 6am 的范围。 (即中午 11 点、中午 12
使用 Joda 时间并获得类似以下行为的最简单方法是什么: public boolean check( DateTime checkTime ) { DateTime someTime = n
我想计算 updated_at 比 created_at 早 2 小时的记录。 代码 $teLang = $kentekens->where('updated_at', '>', 'created_a
我是一名优秀的程序员,十分优秀!