0

Sample.xml:

`id1のテストポイントlvl3id1のlvl4

<tester>
   <level1 id="2"> test point </level1>
   <level2> </level2>
   <level3>lvl3 of id 2 </level3>
   <level4> lvl4 of id 2</level4>
   <level5> </level5>
</tester>

<tester>
   <level1 id="3"> test point </level1>
   <level2> </level2>
   <level3>lvl3 of id 3</level3>
   <level4>lvl4 of id 3</level4>
   <level5> </level5>
</tester>

<tester>
   <level1 id="2"> test point </level1>
   <level2> </level2>
   <level3>lvl3 of id 2 2nd occurance</level3>
   <level4>lvl4 of id 2 2nd occurance</level4>
   <level5> </level5>
</tester>

`
上記のsample.xmlの場合、level1のID2の場合にのみ、level3およびlevel4タグを取得する必要があります。例: id = 2を検索すると、次の答えが得られるはずです。

<level3>lvl3 of id 2 </level3>
<level4> lvl4 of id 2</level4>

<level3>lvl3 of id 2 2nd occurance</level3>
<level4>lvl4 of id 2 2nd occurance</level4>
4

3 に答える 3

2

sedの使用:

sed -n '/<tester>/{n;/<level1[ ]*id="2"/{n;n;N;p}}' input

説明:

sed                  # execute sed
-n                   # do not print unless explicitly stated
/<tester>/           # if this line contains <tester>
{                    # then 
n;                   # skip the line (read new line over the old line)
/<level1[ ]*id="2"/  # if this line contains <level1 [spaces] id="2"
{                    # then
n;n;                 # skip it, and skip the next line
N;                   # read another line but this time append
p                    # print the buffer
}                    # end if
}                    # end if
于 2013-02-04T08:30:29.157 に答える
0

xmlstarletのようなxmlパーサーをお勧めします。ただし、それはを使用して実行できないということではありませんawk。これが1つの方法です。次のように実行します:

awk -f script.awk file

内容script.awk

/<tester>/ {
    r=""
    f=1
}

f && /<level1 id="2">/ {
    g=1
}

g && /<level[34]>/ {
    sub(/^[ \t]+/, "")
    r = r $0 ORS
}

/<\/tester>/ {
    if (g && r) {
        print r
    }
    f=g=0
}

結果:

<level3>lvl3 of id 2 </level3>
<level4> lvl4 of id 2</level4>

<level3>lvl3 of id 2 2nd occurance</level3>
<level4>lvl4 of id 2 2nd occurance</level4>

または、これがワンライナーです。

awk '/<tester>/ { r=""; f=1 } f && /<level1 id="2">/ { g=1 } g && /<level[34]>/ { sub(/^[ \t]+/, ""); r = r $0 ORS } /<\/tester>/ { if (g && r) print r; f=g=0 }' file
于 2013-02-04T08:30:26.980 に答える
0

awkでブロックを操作する場合、RSをクリアすると便利なことがよくあります。私はこれがあなたが望むことをすることを信じています:

awk '/id="2"/{print ""; split( $0,a,"\n" ); for( i in a) 
    if( match( a[i], "level[34]" )) print(a[i])}' RS= input
于 2013-02-04T13:29:19.390 に答える