使用 egrep 但开始考虑 awk 或 sed 可能是解决方案

Using egrep but starting to think awk or sed might be the solution

首先,我使用的是 Cygwin mintty 2.7.4,所以... posix。我在类似于以下内容的文件中存在多个代码片段:

<blah>Spread the peanut butter <ramout assot="f0123_fun10" bapel="2 or 6"/> on good looking bread <ramout assot="f0123_fun10" bapel="3 or 5"/> that does not have peanut butter <ramout assot="f0123_fun10" bapel="2 or 6"/> already on the bread this that and the other <ramout assot="f0123_fun10" bapel="4"/> with something else.</blah>

我试图在一组 blah 标签中找到 ramout 标签的重复实例。 如果存在以下情况:

<ramout assot="f0123_fun10" bapel="2 or 6"/> 

我想知道它是否在一组开始和结束的 blah 标签中再次重复。

我试过很多东西。最新的一项如下:

grep -Eoi '<blah>.*([[:space:]]<ramout assot).*.*</blah>' *.xml | less

什么也没返回。

我也试过:

 grep -Eio '<blah>.*([[:space:]]<ramout assot="[a-z][0-9]{5}_fig[0-9]+" bapel="[0-9]+.*)' *.xml

其中不包括网络结果但不显示所有结果的反向引用。看起来这只显示了一个 line/do 不跨越多行的结果。

如果我想搜索可能在一行或可能不在一行的内容,我应该使用 sed 吗?

awk 是可行的候选者吗?我看到并尝试了:awk '/Start pattern/,/End pattern/' filename 返回了更多结果,但我仍然没有得到所有结果。

任何能够找到 a) 整个文件中的所有 ramout 结果和单独的 b) blah 标签中重复的所有 ramout 结果的帮助将不胜感激。

预期结果类似于:

搜索结果 a) 显示所有 ramout 结果:

<ramout assot="f0123_fun10" bapel="2 or 6"/>
<ramout assot="f0123_fun10" bapel="3 or 5"/>
<ramout assot="f0123_fun10" bapel="2 or 6"/>
<ramout assot="f0123_fun10" bapel="4"/>

搜索结果 b) 显示重复结果将显示:

<ramout assot="f0123_fun10" bapel="2 or 6"/>

要parse/query XML/XHTML 文档使用以下工具之一:

  • xmlstarlet
  • xmllint
  • saxon-lint

我会建议使用 xmlstarlet 的解决方案。
1) 安装 xmlstarlet 工具
2)使用XmlStarletselectsel选项查询或搜索XML 个文件 (xmlstarlet manual)


a)整个文件中所有<ramout>个标签:

xmlstarlet sel -t -n  -m "//blah/ramout" -c "." -n testfile.xml

输出:

<ramout assot="f0123_fun10" bapel="2 or 6"/>
<ramout assot="f0123_fun10" bapel="3 or 5"/>
<ramout assot="f0123_fun10" bapel="2 or 6"/>
<ramout assot="f0123_fun10" bapel="4"/>

b)<blah> 个标签中重复的所有 <ramout> 个标签:

xmlstarlet sel -t -n  -m "//blah/ramout" -c "." -n testfile.xml | sort | uniq -d

输出:

<ramout assot="f0123_fun10" bapel="2 or 6"/>

uniq -d:
-d, --repeated - 只打印重复行,每组一行

a) sed 's/</\n</g;s/>/>\n/g' pb.txt | sed -n '/<blah/,/<\/blah/{/ramout/p}'

第一次 sed 调用只是确保标记周围的换行符。第二次调用打印 blah 标记之间的每个 ramout 行。语法是 /START/,/END/{/MATCH/p} 意思是从开始到结束,打印匹配的行。

所以你得到这个:

<ramout assot="f0123_fun10" bapel="2 or 6"/>
<ramout assot="f0123_fun10" bapel="3 or 5"/>
<ramout assot="f0123_fun10" bapel="2 or 6"/>
<ramout assot="f0123_fun10" bapel="4"/>

随着 xmlstarlet 答案的建立,您可以将其通过管道传输到 sort,然后是 uniq -d:

b) sed 's/</\n</g;s/>/>\n/g' pb.txt | sed -n '/<blah/,/<\/blah/{/ramout/p}' | sort | uniq -d

对于此输出:

<ramout assot="f0123_fun10" bapel="2 or 6"/>

+1 到 xmlstarlet 的答案,因为它是正确的做事方式,并且成立 sort | uniq -d。但是,如果您知道这种 sed 语法,那么您就有了一把锤子,一切看起来都像钉子。