【问题标题】:find line number of last occurance of pattern before specific line number在特定行号之前查找模式最后一次出现的行号
【发布时间】:2011-08-27 19:32:39
【问题描述】:

我有一个像这样的事件的大文件:

<event>
...
...multiple lines describing the event
...
</event>
<event>
...
... 
<event>

当发生错误时,我会得到发生错误的行号,该行号总是在事件标记中的某个位置结束。我想在错误发生之前和从错误开始的事件中拆分文件。我知道我可以使用

进行拆分
csplit -k filename line_number_to_split_on

我需要做的是找到错误行的前一个事件标记的行号。 文件相当大。例如,我在第 1007425 行列出了一个错误,通过查看文件,事件标签位于第 1007397 行。我想要一种在 shell 脚本中执行此操作的方法。有什么想法吗?

【问题讨论】:

  • 需要有关输入文件的更多信息以及作为输出所需的信息。

标签: xml bash shell sed awk


【解决方案1】:

假设 $LINE 作为发生错误的行号,$FILE 作为输入文件,你可以这样做:

$ nl -ba $文件 | sed -n -e '//p' -e ${LINE}q |尾-1

(您可以在 sed 中使用 '=' 运算符来获取行号而不是 nl,但我更喜欢 nl 并且 = 不是很便携。此外,它会插入额外的换行符,这有点麻烦。)

作为管道到尾部的替代方法,您可以这样做:

$ nl -ba $文件 | sed -n -e '//h' -e$LINE'{x; p; q;}'

【讨论】:

  • 聪明。 linux 有很多命令,即使是有经验的用户也不知道。我最近才听说过 tac,直到现在才听说过 nl。从未见过 = 用于 sed。我从手册页中看到它可以。谢谢
  • 我想指出,如果您在第一个解决方案中将 /&lt;event&gt;/p 替换为 /&lt;event&gt;/=,您将仅获得行号,而不是行号 + 事件标签。 = 命令的打印独立于模式空间(无论如何都被-n 抑制)。至于可移植性,我相信它多年来一直是规范的一部分。
【解决方案2】:

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

#!/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))

测试数据。

 1  <event>
 2  .
 3  .
 4  .
 5  </event>
 6  <event>
 7  ..
 8  ..
 9  ..
10  </event>
11  <event>
12  ...
13  ...
14  ...
15  </event>

输出

foo@ell:/tmp/test$ ./test.sh 3
1
foo@ell:/tmp/test$ ./test.sh 8
6
foo@ell:/tmp/test$ ./test.sh 14
11

【讨论】:

  • 没用。它打印出文件中最后一行的行号
  • 我的错。有效。打开事件标签并没有立即关闭,所以我所要做的就是将 awk 中的“”更改为“
  • 这似乎过于复杂。不过,使用 tac 是个好主意。如果错误发生在第 345 行,您可以简单地执行以下操作: sed 345q input |塔克 | sed -n '//{p; q;}'
【解决方案3】:

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

更新:

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

【讨论】:

  • 我不希望在 vanilla linux 机器上使用其他东西,因为它部署在不希望在他们的机器上安装基本 linux 附带的软件以外的任何软件的站点上
猜你喜欢
  • 2017-01-25
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
  • 1970-01-01
  • 2017-06-17
  • 2013-07-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多