从Bash中的特定行反向搜索图案

问题描述 投票:0回答:2

说我有一个格式很大的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的名称。它不仅非常慢,而且我也希望它是一个与元格式无关的脚本。

bash unix sed text-processing xmlstarlet
2个回答
0
投票

我在这里尝试以下内容:

  1. entry标记行号保存到单独的文件中>>
  2. 指定head
  3. 标签的所需行号
  4. 执行搜索“ 它适合哪里
  5. 输入文件:

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

0
投票

sed之类的工具的问题是,当您要整体处理一大块文件时,它们一次处理一行。输入ed。以下命令将在第3026138行之前找到的第一行与<entry>之间的所有内容打印到该行:

© www.soinside.com 2019 - 2024. All rights reserved.