Xml 查找特定行号之前最后一次出现的图案行号

Xml 查找特定行号之前最后一次出现的图案行号,xml,bash,shell,sed,awk,Xml,Bash,Shell,Sed,Awk,我有一个很大的事件档案,比如: <event> ... ...multiple lines describing the event ... </event> <event> ... ... <event> 我需要做的是找到错误行前一个事件标记的行号。 这些文件相当大。例如,我在第1007425行列出了一个错误,查看文件时,事件标记在第1007397行。我想在shell脚本中实现这一点。有什么想法吗?您的输入看起来像XML。最好的方法是使用XM

我有一个很大的事件档案,比如:

<event>
...
...multiple lines describing the event
...
</event>
<event>
...
... 
<event>
我需要做的是找到错误行前一个事件标记的行号。
这些文件相当大。例如,我在第1007425行列出了一个错误,查看文件时,事件标记在第1007397行。我想在shell脚本中实现这一点。有什么想法吗?

您的输入看起来像XML。最好的方法是使用XML解析器。手工解析XML并不是那么有趣。根据XML解析器的不同,起始行号是元素元数据的一部分。(例如,对于SAX,有。)

更新:


它认为使用正确的工具是一个好主意。如果不能使用XML解析器,则必须为XML子集编写自己的解析器。您应该从查看开始,看看实际需要哪些功能。如果您不必支持递归、XML实体和XML CDATA,那么它将消除很多复杂性。得到这些信息后,您的问题就可以得到回答。

您的输入看起来像XML。最好的方法是使用XML解析器。手工解析XML并不是那么有趣。根据XML解析器的不同,起始行号是元素元数据的一部分。(例如,对于SAX,有。)

更新:


它认为使用正确的工具是一个好主意。如果不能使用XML解析器,则必须为XML子集编写自己的解析器。您应该从查看开始,看看实际需要哪些功能。如果您不必支持递归、XML实体和XML CDATA,那么它将消除很多复杂性。在您获得这些信息后,您的问题就可以得到回答。

我不确定大文件的性能,但它确实有效

#!/bin/sh
total=$(cat EVENTFILE |wc -l)
error=$1 ### Line number where error occurred
from=$((total-error))
num=$(tac EVENTFILE|awk '/<event>/{print NR}'|while read n; do
    echo ${n};
    if test ${n} -ge ${from}; then
        break;
    fi;
    done|tail -1)
echo $((total-num+1))

我不确定大文件的性能,但它可以工作

#!/bin/sh
total=$(cat EVENTFILE |wc -l)
error=$1 ### Line number where error occurred
from=$((total-error))
num=$(tac EVENTFILE|awk '/<event>/{print NR}'|while read n; do
    echo ${n};
    if test ${n} -ge ${from}; then
        break;
    fi;
    done|tail -1)
echo $((total-num+1))

将$LINE作为发生错误的行号,将$FILE作为输入文件,可以执行以下操作:

$ nl -ba $FILE | sed -n -e '/<event>/p' -e ${LINE}q | tail -1 $nl-ba$FILE | sed-n-e'//p'-e${LINE}q | tail-1 (您可以在sed中使用“=”操作符来获取行号,而不是nl,但我更喜欢nl,并且=不是很好移植。此外,它插入了额外的换行符,这有点麻烦。)

作为管道到尾部的替代方案,您可以执行以下操作:

$ nl -ba $FILE | sed -n -e '/<event>/h' -e$LINE'{x; p; q;}' $nl-ba$文件| sed-n-e'//h'-e$行'{x;p;q;}'
将$LINE作为发生错误的行号,将$FILE作为输入文件,可以执行以下操作:

$ nl -ba $FILE | sed -n -e '/<event>/p' -e ${LINE}q | tail -1 $nl-ba$FILE | sed-n-e'//p'-e${LINE}q | tail-1 (您可以在sed中使用“=”操作符来获取行号,而不是nl,但我更喜欢nl,并且=不是很好移植。此外,它插入了额外的换行符,这有点麻烦。)

作为管道到尾部的替代方案,您可以执行以下操作:

$ nl -ba $FILE | sed -n -e '/<event>/h' -e$LINE'{x; p; q;}' $nl-ba$文件| sed-n-e'//h'-e$行'{x;p;q;}'
我不希望在普通linux机器上使用其他软件,因为这是部署在不希望在机器上安装基本linux以外的任何软件的站点上。我不希望在普通linux机器上使用其他软件,因为这是部署在不希望安装基本linux以外的任何软件的站点上机器上安装的linux需要有关输入文件和输出信息的更多信息。需要有关输入文件和输出信息的更多信息。无法工作。它打印出文件My bad中最后一行的行号。成功了。开始事件标记没有立即关闭,所以我所要做的就是将awk中的“”更改为“”这似乎过于复杂。不过,使用tac是一个好主意。如果错误发生在第345行,您只需执行以下操作:sed 345q input | tac | sed-n'/{p;q;}'不起作用。它打印出文件中最后一行的行号我的坏了。它起作用了。开始事件标签没有立即关闭,所以我所要做的就是将awk中的“”更改为“这似乎太复杂了。”。不过,使用tac是个好主意。如果错误发生在第345行,您只需执行以下操作:sed 345q input | tac | sed-n'/{p;q;}'。linux有如此多的命令,甚至有经验的用户都不知道。我最近才听说过tac,直到现在才听说过nl。从未见过=在sed中使用。我从手册页上看到它可以。ThxI想指出的是,如果在第一个解决方案中用
/=
替换
///p
,则只能获得行号,而不能获得行号+事件标记。
=
命令独立于图案空间打印(图案空间被
-n
抑制)。至于可移植性,我相信它已经成为规范的一部分很多年了。linux有如此多的命令,甚至有经验的用户都不知道。我最近才听说过tac,直到现在才听说过nl。从未见过=在sed中使用。我从手册页上看到它可以。ThxI想指出的是,如果在第一个解决方案中用
/=
替换
///p
,则只能获得行号,而不能获得行号+事件标记。
=
命令独立于图案空间打印(图案空间被
-n
抑制)。至于可移植性,我相信它已经成为规范的一部分很多年了。