我正在文件中搜索字符串(字符串包括新行/换行符)并在模式匹配后打印 2 行,例如文件包含:-(已编辑)
<cfu>
<statm1>
<status>good</status>
</cfu>
<cfu>
<statm2>
<status>not found</status>
</cfu>
<cfu>
<statm3>
<status>empty</status>
</cfu>
<cfa>
<statm1>
<status>good</status>
</cfa>
<cfa>
<statm2>
<status>not found</status>
</cfa>
<cfa>
<statm3>
<status>empty</status>
</cfa>
我试过像
awk -v RS=""'/<cfu> <statm1/{i=NR+2}(NR<=i){print}' file_name
但没有运气,请帮忙
预期输出:-
<cfu>
<statm1>
<status>good</status>
</cfu>
答案1
无需尝试解码 XML(无论如何,输入看起来并不完全像 XML),使用 的pcregrep
ultilineM
模式:
$ pcregrep -Mo '(?s)<cfu>(?:(?!</cfu>).)*<statm1>.*?</cfu>' your-file
<cfu>
<statm1>
<status>good</status>
</cfu>
(?s)
打开s
导致.
也匹配换行符的标志。(?!</cfu>).
.
是不是 开头的任意字符 ( )</cfu>
。我们用 匹配 0 个或多个*
。我们用它来代替 来.*
确保我们不会超过下一个结束时间</cfu>
。*?
是 的非贪婪版本*
。
如果您只想要该<status>
值:
$ pcregrep -Mo1 '(?s)<cfu>(?=(?2)*<status>([^<]*))((?!</cfu>).)*<statm1>.*?</cfu>' your-file
good
答案2
使用正确的 HTML/XML 解析器,在用root
节点包围文件后:
和xidel
:
xidel --output-node-format=xml -e '//cfu[contains(., "good")]' file
输出:
<cfu>
<statm1>
<status>good
</status></statm1></cfu>
和xmlstarlet
:
xmlstarlet format -H file | sponge file
xmlstarlet sel -t -c '//cfu[contains(., "good")]' file 2>/dev/null
输出:
<cfu>
<statm1>
<status>good
</status></statm1></cfu>