我拥有的:
interface GigabitEthernet0/2/1/6.2061
description --> Some description here
service-policy input BESTEFFORT-IN
service-policy output Egress_30M
vrf VPN-s2s
ipv4 mtu 1500
ipv4 address 222.222.222.1 255.255.255.252
ipv4 unreachables disable
dot1q vlan 2061
!
interface GigabitEthernet0/2/1/6.2062
description Some Description here too
service-policy input BESTEFFORT-IN
vrf TRUSTED-3879
ipv4 mtu 1500
ipv4 address 111.111.111.111 255.255.255.252
--
[thousands of same data blocks]
我想从中得到什么:
获取模式 1(例如 2/1/6.2061)和块末尾(应该是 ! 字符)之间的所有数据
现在我尝试了使用 sed 和 awk 的多种方法,如许多类似的线程所示:
usr@mpls-fa-1:~/CIRCUITI_DA_DISMETTERE$ awk '/2\/1\/6.2061/{p=1} p; /\!/{exit}' idc3-sfc
usr@mpls-fa-1:~/CIRCUITI_DA_DISMETTERE$
和
usr@mpls-fa-1:~/CIRCUITI_DA_DISMETTERE$ sed -n -e '/2\/1\/6.2061/,/\!/p ; /\!/q' idc3-sfc
usr@mpls-fa-1:~/CIRCUITI_DA_DISMETTERE$
还有更多变体,例如 sed 和 !d 等等。如果我使用
sed -n -e '/2\/1\/6.2061/,/\!/p ;' idc3-sfc
awk '/2\/1\/6.2061/{p=1} p' idc3-sfc
它将显示任何匹配项(所以成千上万行)
我在这里发布的只是我关注的一些主题:
- sed:仅打印模式匹配的第一次出现
- 如何选择两个模式(包括它们)之间的第一次出现
- https://www.linuxquestions.org/questions/programming-9/grep-until-certain-character-or-pattern-appears-816393/
我通过创建一个新文件将示例文本放入其中发现了问题。
如果我使用:
usr@mpls-fa-1:~/CIRCUITI_DA_DISMETTERE$ awk '/2\/1\/6.2061/{p=1} p ; /!/{exit}' TEST
interface GigabitEthernet0/2/1/6.2061
description --> Some description here
service-policy input BESTEFFORT-IN
service-policy output Egress_30M
vrf VPN-s2s
ipv4 mtu 1500
ipv4 address 222.222.222.1 255.255.255.252
ipv4 unreachables disable
dot1q vlan 2061
!
usr@mpls-fa-1:~/CIRCUITI_DA_DISMETTERE$
它有效[因为它是“文本的第一个块”]但是如果我尝试通过点击来获取第二个块:
usr@mpls-fa-1:~/CIRCUITI_DA_DISMETTERE$ awk '/2\/1\/6.2062/{p=1} p ; /!/{exit}' TEST
usr@mpls-fa-1:~/CIRCUITI_DA_DISMETTERE$
它不起作用[因为我正在搜索接口 6.2062 而不是 6.2061]
答案1
您的第一个sed
示例不适用于第二个和后续块,因为/!/q
(反斜杠可能会导致未定义的行为,所以我将其删除)已经在第一个块中执行,!
并且脚本在那里停止(与脚本exit
的相同awk
)。因此仅在块之后执行它,使用
sed -n '/2\/1\/6.2062/,/!/{p;/!/q;}'
但一个简单的
sed -n '/2\/1\/6.2062/,/!/p'
如果你不介意浪费一些CPU周期,就像你的第二次尝试一样。
对于未来的脚本,如果地址模式包含斜杠,我建议使用不同的分隔符,例如
sed -n '\_2/1/6.2062_,/!/p'
更容易阅读,对吗?
是的,您还可以使用!d
:
sed '\_2/1/6.2062_,/!/!d'
答案2
在最后的 awk 脚本更改中:
p ; /!/{exit}
到
p {print; if (/!/) exit}
因此,您在处理您感兴趣的块后退出,而不是在文件中第一个块的末尾退出。