在Awk中配对任意XML打开/关闭标签

时间:2015-09-15 20:32:37

标签: awk

我正在尝试提取看起来像这样的块注释:

<tag_1:sub_tag>
This is 1 comment.
</tag_1:sub_tag>

<any_tag>
This is yet another comment.
</any_tag>

通过

 find . -type f -exec awk '/<variable>/,/<\/variable>/{print FILENAME ":" FNR ":" $0}' {} \;

但我不确定如何让$ variable接受使用外卡*之类的内容。有办法吗?

这必须在子文件夹上递归完成。

2 个答案:

答案 0 :(得分:1)

永远不要使用范围表达式,因为它们只是最简单的工作,但是当问题变得更加有趣时,需要完全重写和/或重复条件。始终使用标志,例如src/main/java

在这种情况下,假设您的输入文件与您提供的示例一样简单且格式良好,因此您不需要XML解析器:

awk '/start/{f=1} f; /end/{f=0}'

只需将其粘贴在awk -v OFS=':' ' match($0,/^<[^\/>]+>$/) { f = 1 end = "</"substr($0,RSTART+1,RLENGTH-1) } f {print FILENAME, FNR, $0} $0 == end { f = 0 } ' file file:1:<tag_1> file:2:This is 1 comment. file:3:</tag_1> file:7:<any_tag> file:8:This is yet another comment. file:9:</any_tag> 命令中,如果您觉得有用,请随意将其全部塞进一行。

如果要更改分隔标记行中的一个或两个是否只是更改设置/清除标记find的位置,例如:

f

因为你似乎对如何运行它感到困惑:

awk -v OFS=':' '
    $0 == end { f = 0 }
    f {print FILENAME, FNR, $0}
    match($0,/^<[^\/>]+>$/) {
        f = 1
        end = "</"substr($0,RSTART+1,RLENGTH-1)
    }
' file
file:2:This is 1 comment.
file:8:This is yet another comment.

$ cat file
<tag_1:sub_tag>
This is 1 comment.
</tag_1:sub_tag>

or

<any_tag>
This is yet another comment.
</any_tag>

$ awk -v OFS=':' ' $0 == end { f = 0 } f {print FILENAME, FNR, $0} match($0,/^<[^\/>]+>$/) { f = 1 end = "</"substr($0,RSTART+1,RLENGTH-1) } ' file file:2:This is 1 comment. file:8:This is yet another comment. 是我的提示。有问题吗?

我仍然不确定你为什么遇到问题,但这有帮助:

$

$ ls
file

$ cat file
<tag_1:sub_tag>
This is 1 comment.
</tag_1:sub_tag>

or

<any_tag>
This is yet another comment.
</any_tag>

$ find . -type f -exec awk -v OFS=':' '
    $0 == end { f = 0 }
    f {print FILENAME, FNR, $0}
    match($0,/^<[^\/>]+>$/) {
        f = 1
        end = "</"substr($0,RSTART+1,RLENGTH-1)
    }
' {} \;
./file:2:This is 1 comment.
./file:8:This is yet another comment.

$ find . -type f -exec awk -v OFS=':' '$0 == end { f = 0 } f {print FILENAME, FNR, $0} match($0,/^<[^\/>]+>$/) { f = 1; end = "</"substr($0,RSTART+1,RLENGTH-1) }' {} \;
./file:2:This is 1 comment.
./file:8:This is yet another comment.

答案 1 :(得分:0)

要求救援!

awk '/<tag_1>/,/<\/tag_1>/' file

如果要将标记名称作为变量传递,可以将其更改为

 awk -v tag="tag_1" '$0~"<"tag">",$0~"</"tag">"' file

这将在任何打开和关闭的标签之间打印值

awk '/<[^/>].*>/{s=1;next} /<\/[^>].*>/{s=0} s' file

然而,不检查它们是否匹配。

我确信它可以进一步简化,但这样可以确保打开和关闭的代码匹配(仍然无法处理嵌套代码)

$ awk '/<[^/>].*>/{sub("<","</");t=$0;delete a;c=0;s=1;next}
             t==$0{for(i=1;i<=c;i++)print a[i];delete a;c=s=0;t=""} 
                 s{a[++c]=$0}' file

在开放标记之后缓冲行,直到找到匹配的关闭标记,然后打印缓冲的行,重置等。