1

我有一个巨大的 XML 文件,我需要提取包含一系列数字的整个标签的内容。文件中的所有内容都是一行,我在此处添加了换行符以使其更具可读性

所以这里我有一个简化的例子

文件:

<ORDERS>
<IDOC BEGIN><tag1>aaa</tag1><tag2>bbb</tag2><tag3>12345</tag3><tag4>ccc</tag4></IDOC>
<IDOC BEGIN><tag1>aaa</tag1><tag2>bbb</tag2><tag3>23456</tag3><tag4>ccc</tag4></IDOC>
<IDOC BEGIN><tag1>aaa</tag1><tag2>bbb</tag2><tag3>0007537181</tag3><tag4>ccc</tag4></IDOC>
<IDOC BEGIN><tag1>aaa</tag1><tag2>bbb</tag2><tag3>34567</tag3><tag4>ccc</tag4></IDOC>
</ORDER>

我想匹配包含序列 0007537181 的 IDOC BEGIN 标签。所以它会是

<IDOC BEGIN><tag1>aaa</tag1><tag2>bbb</tag2><tag3>0007537181</tag3><tag4>ccc</tag4></IDOC>

到目前为止,我得到了这个正则表达式:

cat myfile | grep -oP '<IDOC BEGIN.*?0007536846.*?</IDOC>'

这导致从第一个具有相同名称的标签的开头到我想要的所有内容:

<IDOC BEGIN><tag1>aaa</tag1><tag2>bbb</tag2><tag3>12345</tag3><tag4>ccc</tag4></IDOC>
<IDOC BEGIN><tag1>aaa</tag1><tag2>bbb</tag2><tag3>23456</tag3><tag4>ccc</tag4></IDOC>
<IDOC BEGIN><tag1>aaa</tag1><tag2>bbb</tag2><tag3>0007537181</tag3><tag4>ccc</tag4></IDOC>

我设法通过将其发送到第二个正则表达式来解决此问题,该正则表达式获取 IDOC BEGIN 的最后一次出现

cat myfile | grep -oP '<IDOC BEGIN.*?0007536846.*?</IDOC>' | grep -oP '<IDOC BEGIN(?!.*<IDOC BEGIN).*?</IDOC>'

总结一下,我需要得到数字序列之前的最后一个IDOC BEGIN

请记住,原始文件没有换行符,所有内容都在一行中。

4

1 回答 1

1

您可以使用的正则表达式要么基于放置在开头并后跟\K 匹配重置运算符的贪心点模式,要么基于经过调整的贪心令牌。当涉及部分匹配(但不匹配)的大字符串时,两者都非常不安全。

所以,这两个正则表达式是

.*\K<IDOC BEGIN.*?0007536846.*?</IDOC>
<IDOC BEGIN(?:(?!<IDOC BEGIN).)*?0007536846(?:(?!<IDOC BEGIN).)*?</IDOC>

最好的办法是在这些情况下展开缓和的贪婪令牌:

<IDOC BEGIN[^<]*(?:<(?!IDOC BEGIN)[^<]*?)*0007537181.*?</IDOC>

查看正则表达式演示

第一个.*?替换为[^<]*(?:<(?!IDOC BEGIN)[^<]*?)*

  • [^<]*- 一个否定字符类,匹配 0 个或更多字符,而不是<, 尽可能多
  • (?:<(?!IDOC BEGIN)[^<]*?)*- 0次或多次重复
    • <(?!IDOC BEGIN)-<不紧跟IDOC BEGIN字符串的字符
    • [^<]*?- 一个否定字符类,匹配 0 个或多个字符<,尽可能少
于 2019-09-26T18:05:36.577 回答