【发布时间】:2020-05-21 06:12:24
【问题描述】:
我想编写一个 bash 脚本,它可以识别文本中与多行模式匹配的标签,以便我可以使用识别标签进一步处理嵌套标签以供以后处理。我已经搜索了多个问题,但它们似乎都以某种方式不足,难以取得进展。我成功的是能够匹配模式并获得匹配的行,但是它作为单个输出出现(我相信)。首先是我正在测试的示例文本文件。
random words to put here: dresser car street space
*
********************************************************************************
********************************************************************************
-->
interested data: name="someFile_1.txt"random data
endMultilinePattern
<!--****************Random comment***************-->
startMultilinePattern id="someFileTag_2"
interested data: name="someFile_2.txt"random data
endMultilinePattern
<!--****************Random comment***************-->
startMultilinePattern id="someFileTag_3"
interested data: name="someFile_3.txt"random data
endMultilinePattern
some random data body
some random nested data filepath="/" uuid="randomcharacters"random data
some random data body
more random data
endMultilinePattern
startMultilinePattern id="someFileTag_2"
interested data: name="error_someFileTag_2.txt"random data
endMultilinePattern
<!--****************Random comment***************-->
以下是我得到的一些输出以及导致它们的答案。可能是我自己理解不够,不知道如何正确使用命令。首先,我感兴趣的 id 在startMultilinePattern id="someFileTag_2"> 中,稍后我将在文件中使用id 来匹配使用该id 的其他标签。其次,我想在interested data: name="..."random data 标记中获取属性name,以便在文件系统中搜索该文件以进行进一步处理。在这个问题中,我现在要做的就是获取startMultilinePattern> ... multi-line match ... endMultilinePattern,然后在interested data: name="..."random data 标签中获取文件名。我们开始吧:
以下使用了 perl 的 grep 中的 -P 选项,虽然它得到了正确的输出,但我似乎无法读入数组并输出每个多行匹配。
源:grep (bash) multi-line pattern
$ $ grep -Pzon "((startMultilinePattern )(.|\n)*?(endMultilinePattern))" test.txt | while read -a grepOut; do POS=$((POS+1)) && echo "0=${grepOut[0]}, 1=${grepOut[1]}, 2=${grepOut[2]}, 3=${grepOut[3]}}";done 0=1:startMultilinePattern, 1=id="someFileTag_2", 2=, 3=}
0=interested, 1=data:, 2=name="someFile_2.txt"random, 3=data}
0=endMultilinePattern1:startMultilinePattern, 1=id="someFileTag_3", 2=, 3=}
0=interested, 1=data:, 2=name="someFile_3.txt"random, 3=data}
0=endMultilinePattern1:startMultilinePattern, 1=id="someFileTag_2", 2=, 3=}
0=interested, 1=data:, 2=name="error_someFileTag_2.txt"random, 3=data}
# grep command by itself provides the following output:
1:startMultilinePattern id="someFileTag_2"
interested data: name="someFile_2.txt"random data
endMultilinePattern1:startMultilinePattern id="someFileTag_3"
interested data: name="someFile_3.txt"random data
endMultilinePattern1:startMultilinePattern id="someFileTag_2"
interested data: name="error_someFileTag_2.txt"random data
endMultilinePattern
使用 sed 大概应该更合适,我找到了这个有趣的答案,但我无法让它工作。它使用了一些我不明白的时髦的开始关键字。 源:https://unix.stackexchange.com/questions/112132/how-can-i-grep-patterns-across-multiple-lines
sed -n '/\startMultilinePattern /{:start /endMultilinePattern/!{N;b start};/startMultilinePattern .*\n.*\n.*endMultilinePattern/p}' test.txt
此外,下面的 sed 命令据说可以作为它的许多答案,但可能是它的旧功能。我无法让它工作,因为输出看起来不像预期的那样。它包括我不想要的部分文本,即<some random data body ....。
源:https://unix.stackexchange.com/a/112134/388443
$ sed -e '/startMultilinePattern /,/endMultilinePattern/!d' test.txt
startMultilinePattern id="someFileTag_2"
interested data: name="someFile_2.txt"random data
endMultilinePattern
startMultilinePattern id="someFileTag_3"
interested data: name="someFile_3.txt"random data
endMultilinePattern
startMultilinePattern id="someFileTag_2"
interested data: name="error_someFileTag_2.txt"random data
endMultilinePattern
还有其他答案有他们自己的做法。有些人使用 awk,我不知道 awk 所以没有尝试,我也不能使用 pcregrep,因为我没有安装它的 root 权限。据我了解, grep -P 或多或少等同于 pcregrep。想法?
【问题讨论】:
-
Don't Parse XML/HTML With Regex. 我建议使用 XML/HTML 解析器 (xmlstarlet, xmllint ...)。
-
谢谢,我会检查一下,但 XML 不仅仅是问题的特定上下文的要求。文件类型和 XML 标签是间接的,而不是我唯一的输入文件。我会将文件视为一般文本,因此无论文件类型如何,我都在寻找正则表达式的一般解决方案。在我处理它时,我可能希望将此解决方案重用于其他类型的情况。
-
重申我正在寻找的是:一种可以匹配多行模式的方法,我可以在给定文件中提取模式的每次出现以提取更多数据。看这篇文章,它很有趣,但后来它谈到了复杂性和 XML 复杂性 > 正则表达式复杂性,这就是为什么你不对 XML 使用正则表达式的原因。我理解这一点,但我相信我的输入文件过于简化和控制对于正则表达式来说过于复杂。见:stackoverflow.com/a/1758162/10421103