说我有一个格式很大的XML字典:
<entry>
<!-- arbitrary amount of lines -->
<head>SomeWord</head>
<!-- arbitrary amount of lines -->
</entry>
并且假设我知道SomeWord在3026138行上。我想从3,026,138行向后搜索,直到<entry>
,但我不知道<entry>
和目标行之间有多少行。
[This answer如果我使用行号而不是模式,则可以正常工作,如下所示
sed '/<entry>/h;//!H;3026138!d;x;q' file
但是,这是次优的解决方案,因为我认为sed
正在从第0行进行扫描,并在文件中爬行了300万行。这似乎很浪费,因为我已经知道我要处理文件的哪个区域。总共大约需要半秒钟。
没有人能利用我知道行号的事实,而使用所有人都已经拥有的普通Unix / sh程序(例如grep,awk,sed等)的解决方案吗?
注意:请不要建议我使用类似xmllint
的名称。它不仅非常慢,而且我也希望它是一个与元格式无关的脚本。
我在这里尝试以下内容:
输入文件:
someline someline <entry> someline someline <head>Here</head> someline </entry> someline <entry> someline <head>Another</head> someline someline someline </entry> someline someline
shell脚本(可以分隔以对给定的($ 1)行号执行搜索。对文件执行多次搜索或以多种方式使用它(通过不同的方法获取所需的标签,然后将行号提供给搜索脚本以执行搜索)
# preparation before doing searches ln=12 # line number with desired <head> cat input.txt | sed '$a<entry>' | grep -n '^<entry>' | cut -d ':' -f1 > entryl.txt # doing searches t=0 for x in $(seq $(cat entryl.txt | wc -l)); do c=$(cat entryl.txt | head -n $x | tail -n 1) if test $t -eq 1; then if test $ln -lt $c; then echo "<head> tag on line: $ln" echo "Previous <entry> found at: $p" echo "Next <entry> found at: $c" break; else p=$c fi else if test $ln -gt $c; then p=$c; t=1 fi fi done
样本输出:
<head> tag on line: 12
Previous <entry> found at: 10
Next <entry> found at: 19
sed
之类的工具的问题是,当您要整体处理一大块文件时,它们一次处理一行。输入ed
。以下命令将在第3026138行之前找到的第一行与<entry>
之间的所有内容打印到该行: