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

时间:2015-10-27 13:19:49

标签: bash awk sed ksh

我有以下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,我会很感激,如果你发布它:)

按要求编辑:

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>

2 个答案:

答案 0 :(得分:1)

这个awk成语将在模式前面打印n行。

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

例如

$awk -v n=5 '{a[p]=$0; 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]=$0; 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]=$0; 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>

答案 1 :(得分:0)

如果您的grep版本支持-A和-B,并且您的文件是使用固定行创建的,则可以使用

grep -A2 -B6 "Name=Andy" request

使用你的知识可以帮助你做出以下命令:

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

我使用.作为斜杠,我不想逃避角色。只有当安迪成为第一个名字时,这才有效。

让安迪在其他地方工作变得更加棘手:

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