打印 sed/awk 开始表达式上方的四行

print the four lines above the sed/awk start expression

我有以下 sed 命令,它可以取回整个日志块,其中包含 <interface> XML 并打印到 txt 文件中:

sed -n '/(StartingExpression)/{:start /<\/Interface>/!{N;b start};/(SomeValueInTheXML)"/p}' *.log > File.txt

问题是我有一些动态值(时间戳)总是在 (StartingExpression) 上方 4 行...有没有办法打印类似:

line of (StartingExpression) -4

?

我发现了这个问题: search (e.g. awk, grep, sed) for string, then look for X lines above and another string below 但解决方案并不是很清楚:\

感谢您的帮助。

此外,如果有人有学习 sed 的好资源,我将不胜感激post :)

根据请求编辑:

one
two
1/1/2015
line 1
12345
(StartingExpression)
<Interface>
   <A>
   Name=Andy
   </A>
</Interface>
three
four
1/1/2015
line 1
12345
(StartingExpression)
<Interface>
   <A>
   Name=John
   </A>
</Interface>
hello
world

我想从 1/1/2015(在 (StartingExpression) 上方 3 行 - 这可以是动态的日期)打印到 </Interface>

编辑:我忘了说,这些接口可以有多个实例……你如何确保只打印具有 Name=Andy 的接口?

file.txt:

1/1/2015
line 1
12345
(StartingExpression)
<Interface>
   <A>
   Name=Andy
   </A>
</Interface>

这个 awk 习语将打印模式之前和包括模式的 n 行。

$awk -v n="$plines" '{a[p]=[=10=]; p=(p+1)%n} /pattern/{for(i=p;i<p+n;i++) print a[i%n]}' file

例如

$awk -v n=5 '{a[p]=[=11=]; p=(p+1)%n} /20/{for(i=p;i<p+n;i++) print a[i%n]}' <(seq 10 99)

16
17
18
19
20

更新更多逻辑。

您也可以轻松地在图案匹配后合并打印。该脚本将打印之前的行;现在在比赛结束后直到关闭标签结束。

$ awk -v n=4 '           {a[p]=[=12=]; p=(p+1)%n} 
   /(StartingExpression)/{for(i=p;i<p+n-1;i++) print a[i%n];f=1} 
                        f{print} 
            /\/Interface/{exit}' file

1/1/2015
line 1
12345
(StartingExpression)
<Interface>
   <A>
   </A>
</Interface>

更新:基于属性值的过滤器

此时通过另一个脚本而不是重写它会更容易。用 f=0 替换出口,第一个脚本将输出所有匹配的记录并在第二个脚本中过滤感兴趣的记录。

$ awk -v n=4 '           {a[p]=[=13=]; p=(p+1)%n}
   /(StartingExpression)/{for(i=p;i<p+n-1;i++) print a[i%n];f=1}
                        f{print}
            /\/Interface/{f=0}' file
| awk 'BEGIN{ORS=RS="</Interface>\n"} 
 /Name=Andy/'


1/1/2015
line 1
12345
(StartingExpression)
<Interface>
   <A>
   Name=Andy
   </A>
</Interface>

当你有一个支持-A和-B的grep版本,并且你的文件是用固定行制作的,你可以使用

grep -A2 -B6 "Name=Andy" request

使用您的 vi 知识可以帮助您执行以下命令:

echo "/(StartingExpression)/-3,/<.Interface>/ p" | ed -s request

我在 中使用了 . 作为斜线,我不想转义这个字符。这仅在 Andy 是名字时有效。

在其他地方与安迪合作变得更加棘手:

rm /tmp/andy
echo "/Name=Andy/
?(StartingExpression)
-3,/<.Interface>/ w /tmp/andy" | ed -s request 2>&1 >/dev/null
cat /tmp/andy
rm /tmp/andy