string - 删除文件中的半唯一字符串

标签 string awk sed diff uniq

我正在编写一个脚本来跟踪路由表中的更改。该脚本每 5 分钟提取一次路由表快照,并将该表与 5 分钟前的版本进行比较。如果文件中存在偏差,脚本会生成一封电子邮件。问题是每条线还有一个年龄计数器,代表这条路线的年龄,所以这个字段总是在变化。这是来自生产路由器的修改后的快照:

编辑 为了完整性,添加了具有秒和分钟年龄的路由。

B*    0.0.0.0/0 [200/0] via 1.0.10.121, 1d13h
                [200/0] via 1.0.10.111, 1d13h
      10.0.0.0/8 is variably subnetted, 159 subnets, 7 masks
O N1     10.0.0.1/32 [210/21] via 172.18.10.27, 1d13h, Vlan1503
O N1     10.1.0.0/16 [210/21] via 172.18.10.51, 2d17h, Vlan1506
O N1     10.2.0.0/16 [210/21] via 172.18.10.59, 2d17h, Vlan1507
B        10.10.0.0/16 [200/0] via 0.0.0.0, 2d17h, Null0
B        10.186.14.0/24 [200/0] via 1.0.10.124, 1d13h
                        [200/0] via 1.0.10.114, 1d13h
B        10.186.15.0/24 [200/0] via 1.0.10.124, 1d13h
O N2     10.192.32.0/21 [210/20] via 172.18.10.243, 2d17h, Vlan1508
O N2     10.192.40.0/21 [210/20] via 172.18.10.243, 2d17h, Vlan1508
B        10.193.0.0/24 [200/0] via 1.0.10.124, 1d13h
                       [200/0] via 1.0.10.114, 1d13h
C        172.18.10.232/29 is directly connected, Vlan1589
L        172.18.10.233/32 is directly connected, Vlan1589
B        205.1.2.3/27 [200/21] via 1.0.30.5, 2d17h
B     205.3.2.1/24 [200/20] via 1.0.30.5, 2d17h
O N1     2.2.2.2 [110/2] via 192.168.0.2, 00:08:48, Vlan1500
O N1     10.10.83.0/24 [210/21] via 172.18.10.27, 00:00:48, Vlan1503

请注意所有“2d17h”、“1d13h”等,这些是永远增加的年龄计数器,直到设备出现故障或链路抖动,然后它们会重置。然而,路线的年龄对我来说并不是那么重要,只是路线存在并且“下一跳”(又名通过)没有改变。否则,我只会“wc -l”这两个文件并确保长度相同。

从文件中剥离年龄计数器然后比较它们是否可行?如果是这样,删除计数器的最佳方法是什么?

谢谢!

编辑 所需的输出将是相同的,但删除了年龄计数器,如下所示:

B*    0.0.0.0/0 [200/0] via 1.0.10.121,
                [200/0] via 1.0.10.111,
      10.0.0.0/8 is variably subnetted, 159 subnets, 7 masks
O N1     10.0.0.1/32 [210/21] via 172.18.10.27, , Vlan1503
O N1     10.1.0.0/16 [210/21] via 172.18.10.51, , Vlan1506
O N1     10.2.0.0/16 [210/21] via 172.18.10.59, , Vlan1507
B        10.10.0.0/16 [200/0] via 0.0.0.0, , Null0
B        10.186.14.0/24 [200/0] via 1.0.10.124,
                        [200/0] via 1.0.10.114,
B        10.186.15.0/24 [200/0] via 1.0.10.124,
O N2     10.192.32.0/21 [210/20] via 172.18.10.243, , Vlan1508
O N2     10.192.40.0/21 [210/20] via 172.18.10.243, , Vlan1508
B        10.193.0.0/24 [200/0] via 1.0.10.124,
                       [200/0] via 1.0.10.114,
C        172.18.10.232/29 is directly connected, Vlan1589
L        172.18.10.233/32 is directly connected, Vlan1589
B        205.1.2.3/27 [200/21] via 1.0.30.5,
B     205.3.2.1/24 [200/20] via 1.0.30.5,
O N1     2.2.2.2 [110/2] via 192.168.0.2, , Vlan1500
O N1     10.10.83.0/24 [210/21] via 172.18.10.27, , Vlan1503

我试图防止的是两个相同的表(相同数量的路由,相同的下一跳)因差异而失败,因为其中一个路由年龄计数器在路由表的快照之间被勾选。示例:

  1. 脚本对路由表进行快照,一切正常,但有一条路由的年龄为 00:59:59(59 分 59 秒)
  2. 5 分钟后脚本获取路由表的快照,没有路由被删除或添加,但当前表和 5 分钟旧表之间的差异失败,因为 00:59:59 的路由现在是 1d0h 旧(我假设计数器是 1d0h,需要确认它不是 2d1h)

所以我的想法是,如果我去掉所有年龄计数器,差异就不会失败。这可能不是实现监控路由表目标的最佳方式。不幸的是,我在脚本或编程方面没有很强的背景。但是,我对想法持开放态度,欢迎所有建议。 :)

最佳答案

要从示例输入中删除年龄值,您可以匹配整个目标行的语法,而不是“剧烈变化的时间戳”。
(您的评论中措辞优美的摘要,谢谢。)

sed -E "s/(^[^.]*(([[:digit:]]+\.){3}[[:digit:]]+\/[[:digit:]]+| +).* via ([[:digit:]]+\.){3}[[:digit:]]+), [[:digit:]:dh]+/\1/"

(GNU sed 版本 4.2.1,即支持 -E )

  • -E为方便起见,使用扩展的正则表达式
  • s/<start><blabla><IPa_or_spaces> via <IPb><, age><blabla><end>/<same_without_age>/ ,
    从看起来合适的行中删除年龄

我还删除了丑陋的“,”,随着年龄的增长。
如果您想保留它,请替换 ), -> , ) ,即 para 在冒号空格之后而不是之前。

我认为这对于与 sed 相关的事情来说是最复杂的,它接近于 sed-brain-teaser(这是我这样做的真正原因,为了好玩)。
此外,任何语法更改都可能破坏此功能。
因此,请仔细查看 awk 或 perl 中的答案,它们很快就会出现。 ;-)
然后使用您最喜欢的任何东西,例如您自己最了解的语言/工具。

关于string - 删除文件中的半唯一字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45126208/

相关文章:

string - 如何使用 DisplayFormat 在数字之间添加空格

java - 我怎样才能把一个字符串放在一行中

java - 星号字符串,屏蔽密码

python - 如何使用正则表达式查找调用自身的函数?

c++ - 从字符串中删除行注释

bash - 使用 sed 或 awk 或任何东西有条件地删除前 N 个字符

狂欢 : Check if file contains other file contents

bash - Grep 该字符串的第一行并将其保存在变量中以 wget 吗?

regex - 用下划线替换字符串中的所有非字母数字字符

regex - 为什么顺序在 sed 中的这个转义字符类中很重要?