繁体   English   中英

从 Bash 中的特定行反向搜索模式

[英]Reverse Search for Pattern from Specific Line in Bash

假设我有一个大的 XML 字典,格式如下:

<entry>
<!-- arbitrary amount of lines -->
<head>SomeWord</head>
<!-- arbitrary amount of lines -->
</entry>

假设我知道 SomeWord 位于第 3,026,138 行。 我想从第 3,026,138 行向后搜索直到<entry> ,但我不知道<entry>和我的目标行之间有多少行。

如果我使用行号而不是模式,则此答案正常工作,如下所示

sed '/<entry>/h;//!H;3026138!d;x;q' file

然而,这是一个有点次优的解决方案,因为我认为sed是从第 0 行扫描并在文件中爬行 300 万行。 这似乎很浪费,因为我已经知道我想要在文件的哪个区域工作。总而言之,大约需要半秒钟。

有没有人有一个解决方案,利用我知道行号这一事实,使用每个人都已经拥有的普通 Unix/sh 程序(例如 grep、awk、sed 等)?

注意:请不要建议我使用xmllint类的xmllint 它不仅非常慢,而且我还希望这是一个与元格式无关的脚本。

sed工具的问题在于它们一次只处理一行,当您想将文件的一大块作为一个整体处理时。 输入ed 以下内容打印了在第 3026138 行之前找到的带有<entry>的第一行到该行之间的所有内容:

echo "3026138;?<entry>?,.p" | ed -s file

(设置当前行为3026138行,打印当前行之前<entry>的第一个匹配到当前行的范围。如果你想把chunk保存在另一个文件中,你可以用w foo.txt代替p )。

使用示例文件和第 3 行的示例:

$ echo "3;?<entry>?,.p" | ed -s input.txt
<entry>
<!-- arbitrary amount of lines -->
<head>SomeWord</head>

在这里,我尝试了以下操作:

  1. 条目标记行号保存到单独的文件中
  2. 指定所需的head标签行号
  3. 执行搜索“它适合哪里

输入文件:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM