在shell中匹配后在n行内grep

时间:2015-10-23 11:55:49

标签: recursion grep match

有很多文章解释了如何在shell中的grep匹配之后或之前显示n行。

我需要一个更复杂的解决方案:grep for a word,当匹配时,我需要在接下来的n行中进一步grep。理想情况下,因此我需要与第一个搜索匹配的所有行,并且DID与下一个n行中的grep不匹配。某种文本搜索递归。

这不是grep绑定,但可以使用任何Linux / Unix工具。

示例输出:

interface TenGigE0/3/0/0
 description 
 service-policy output QOS
 ipv4 mtu 1500
 ipv4 address 13.24.15.3 255.255.255.252
 carrier-delay up 3000 down 0
 load-interval 30
 dampening
!
interface TenGigE0/3/0/1
 description Link To 
!
interface TenGigE0/3/0/1.302
 description 
 vrf 1671
 ipv4 address 13.24.14.11 255.255.255.254
 encapsulation dot1q 302

我只需要一个在配置中没有vrf行的接口列表。请注意,我从备份数据库获得此输出,而不是路由器本身。

我的一个笨拙的想法是合并“界面”和“界面”之间的所有文字!在一行中过滤掉包含单词“vrf”的行。我使用了awk'/ ^ interface /,/!/'但未能将输出合并为一行。

1 个答案:

答案 0 :(得分:1)

我绝对肯定这可以更有效地完成,但我不是bash巫师。对this answer的充分赞誉。

您的意见。

interface TenGigE0/3/0/0
 description
 service-policy output QOS
 ipv4 mtu 1500
 ipv4 address 13.24.15.3 255.255.255.252
 carrier-delay up 3000 down 0
 load-interval 30
 dampening
!
interface TenGigE0/3/0/1
 description Link To
!
interface TenGigE0/3/0/1.302
 description
 vrf 1671
 ipv4 address 13.24.14.11 255.255.255.254
 encapsulation dot1q 302
!

由于您希望所有接口都没有vrf,我们希望

interface TenGigE0/3/0/0
interface TenGigE0/3/0/1

这将打印该输出。

first_search="^interface"
second_search="vrf"
file="interface.txt"
for line in $(grep -n "$first_search" $file | sed s'/:.*//'); do
  if ! $( sed -n $line',/!/!d;p' $file \
    | grep -q $second_search ); then
    sed -n $line','$line'p' $file
  fi
done

其中$first_search是“紧跟''接口'后面的行的开头”,而$second_search只是文本'vrf'。我将输出写入名为“interface.txt”的文件并将其分配给变量。

这是它的工作原理。执行这些部分中的每一部分以查看数据如何在它们之间传递。

  • grep -n "$first_search" $file找到每个接口实例并打印找到它的行号。此输出通过管道输送到...
  • sed s'/:.*//',删除grep中包括和后面的任何内容。我们只剩下匹配的行号。对于每一个,
  • 再次读取文件并删除除匹配和“!”之外的所有行,然后打印剩余的行(sed -n $line',/!/!d;p')。请参阅上面引用的答案,详细说明这一点。
  • 如果这些行中的任何一行包含“vrf”(grep -q $second_search),则不执行任何操作。否则,
  • 使用sed -n $line','$line'p' $file打印找到原始匹配的行。

注意:我添加了一个“!”到你的输入结束,因为我不想寻找“!”或EOF。