Sed脚本匹配条件在文件末尾失败
我正在使用以下脚本使Sed脚本匹配条件在文件末尾失败,sed,Sed,我正在使用以下脚本使ip addr每个接口打印一行: ip addr | sed -nr '/^\w+: /{ H :top n /^\s/ { H ; b top } x s/\n//g a \ ========== p b top } ' 输入: 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN link/lo
ip addr
每个接口打印一行:
ip addr | sed -nr '/^\w+: /{
H
:top
n
/^\s/ { H ; b top }
x
s/\n//g
a \ ==========
p
b top
}
'
输入:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth2: <BROADCAST,MULTICAST,NOARP,PROMISC,UP,LOWER_UP> mtu 1600 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:33:58:cb brd ff:ff:ff:ff:ff:ff
inet6 fe80::a00:27ff:fe33:58cb/64 scope link
valid_lft forever preferred_lft forever
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 08:00:27:33:58:ca brd ff:ff:ff:ff:ff:ff
inet 192.168.122.10/24 brd 192.168.122.255 scope global eth0
inet6 fe80::a00:27ff:fe33:58ca/64 scope link
1:lo:mtu 65536 qdisc noqueue状态未知
链接/环回00:00:00:00:00 brd 00:00:00:00:00:00:00
inet 127.0.0.1/8范围主机lo
inet6::1/128作用域主机
永远有效\u lft首选\u lft永远有效
2:eth2:mtu 1600 qdisc pfifo_快速状态升级qlen 1000
链接/以太08:00:27:33:58:cb brd ff:ff:ff:ff:ff:ff:ff
inet6 fe80::a00:27ff:fe33:58cb/64范围链接
永远有效\u lft首选\u lft永远有效
3:eth0:mtu 1500 qdisc pfifo_快速状态升级qlen 1000
链接/以太08:00:27:33:58:ca brd ff:ff:ff:ff:ff:ff:ff
inet 192.168.122.10/24 brd 192.168.122.255作用域全局eth0
inet6 fe80::a00:27ff:fe33:58ca/64范围链接
输出:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host valid_lft forever preferred_lft forever
==========
2: eth2: <BROADCAST,MULTICAST,NOARP,PROMISC,UP,LOWER_UP> mtu 1600 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:33:58:cb brd ff:ff:ff:ff:ff:ff inet6 fe80::a00:27ff:fe33:58cb/64 scope link valid_lft forever preferred_lft forever
==========
1:lo:mtu 65536 qdisc noqueue状态未知链接/环回00:00:00:00:00:00 brd 00:00:00:00:00 inet 127.0.0.1/8作用域主机lo inet 6::1/128作用域主机有效\u lft永远首选\u lft永远
==========
2:eth2:mtu 1600 qdisc pfifo\u快速状态升级qlen 1000链路/以太08:00:27:33:58:cb brd ff:ff:ff:ff:ff:ff:ff inet6 fe80::a00:27ff:fe33:58cb/64作用域链路永久有效\u lft首选\u lft永久
==========
错误:最后一个接口总是丢失。如何修复它?这里的问题是
n
的行为
发件人:
n
如果未禁用“自动打印”,请打印图案空间,然后无论如何,用下一行输入替换图案空间。如果没有更多的输入,那么sed将退出,而不处理更多的命令
所以你没有机会对最后一个字段做任何事情,因为sed过早地离开了你。对于n
来说,这似乎是非常奇怪的行为,但事实就是这样
使用awk
可以很容易地做到这一点:
ip addr show | awk '/^\w+: / {
if (iface) {print iface}
iface=$0
next
}
{iface=iface OFS $0}
END {print iface}'
但是根据您接下来需要做什么,直接在
awk
中进行所有处理可能同样容易。这里的问题是n
的行为
发件人:
n
如果未禁用“自动打印”,请打印图案空间,然后无论如何,用下一行输入替换图案空间。如果没有更多的输入,那么sed将退出,而不处理更多的命令
所以你没有机会对最后一个字段做任何事情,因为sed过早地离开了你。对于n
来说,这似乎是非常奇怪的行为,但事实就是这样
使用awk
可以很容易地做到这一点:
ip addr show | awk '/^\w+: / {
if (iface) {print iface}
iface=$0
next
}
{iface=iface OFS $0}
END {print iface}'
但是,根据您接下来需要做什么,直接在
awk
中进行所有处理可能同样容易。天哪,只要使用awk
:
$ awk -v RS= '{gsub(/\n\s+/," ")}1' file
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: eth2: <BROADCAST,MULTICAST,NOARP,PROMISC,UP,LOWER_UP> mtu 1600 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:33:58:cb brd ff:ff:ff:ff:ff:ff inet6 fe80::a00:27ff:fe33:58cb/64 scope link valid_lft forever preferred_lft forever
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:33:58:ca brd ff:ff:ff:ff:ff:ff inet 192.168.122.10/24 brd 192.168.122.255 scope global eth0 inet6 fe80::a00:27ff:fe33:58ca/64 scope link
$awk-vrs='{gsub(/\n\s+/,“”)}1'文件
1:lo:mtu 65536 qdisc noqueue状态未知链接/环回00:00:00:00:00 brd 00:00:00:00:00:00:00:00 inet 127.0.0.1/8作用域主机lo inet 6::1/128作用域主机有效\u lft永远首选\u lft永远
2:eth2:mtu 1600 qdisc pfifo\u快速状态升级qlen 1000链路/以太08:00:27:33:58:cb brd ff:ff:ff:ff:ff:ff:ff inet6 fe80::a00:27ff:fe33:58cb/64作用域链路永久有效\u lft首选\u lft永久
3:eth0:mtu 1500 qdisc pfifo_快速状态升级qlen 1000链路/以太08:00:27:33:58:ca brd ff:ff:ff:ff:ff:ff:ff inet 192.168.122.10/24 brd 192.168.122.255作用域全局eth0 inet 6 fe80::a00:27ff:fe33:58ca/64作用域链路
sed
用于单个行上的简单替换,不适用于涉及多行的任何内容。20世纪70年代中期,awk
发明时,所有用于跨多行操作的SED神秘结构都已过时。现在人们只把它们用于脑力练习,看看它们是否能用sed解决这个难题——实际上,你不会在代码中使用由此产生的咒语
如果您的awk不支持
\s
(gawk
支持),请将\s
更改为上面的[:space:]
。天哪,使用awk
:
$ awk -v RS= '{gsub(/\n\s+/," ")}1' file
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host lo inet6 ::1/128 scope host valid_lft forever preferred_lft forever
2: eth2: <BROADCAST,MULTICAST,NOARP,PROMISC,UP,LOWER_UP> mtu 1600 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:33:58:cb brd ff:ff:ff:ff:ff:ff inet6 fe80::a00:27ff:fe33:58cb/64 scope link valid_lft forever preferred_lft forever
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000 link/ether 08:00:27:33:58:ca brd ff:ff:ff:ff:ff:ff inet 192.168.122.10/24 brd 192.168.122.255 scope global eth0 inet6 fe80::a00:27ff:fe33:58ca/64 scope link
$awk-vrs='{gsub(/\n\s+/,“”)}1'文件
1:lo:mtu 65536 qdisc noqueue状态未知链接/环回00:00:00:00:00 brd 00:00:00:00:00:00:00:00 inet 127.0.0.1/8作用域主机lo inet 6::1/128作用域主机有效\u lft永远首选\u lft永远
2:eth2:mtu 1600 qdisc pfifo\u快速状态升级qlen 1000链路/以太08:00:27:33:58:cb brd ff:ff:ff:ff:ff:ff:ff inet6 fe80::a00:27ff:fe33:58cb/64作用域链路永久有效\u lft首选\u lft永久
3:eth0:mtu 1500 qdisc pfifo_快速状态升级qlen 1000链路/以太08:00:27:33:58:ca brd ff:ff:ff:ff:ff:ff:ff inet 192.168.122.10/24 brd 192.168.122.255作用域全局eth0 inet 6 fe80::a00:27ff:fe33:58ca/64作用域链路
sed
用于单个行上的简单替换,不适用于涉及多行的任何内容。20世纪70年代中期,awk
发明时,所有用于跨多行操作的SED神秘结构都已过时。现在人们只把它们用于脑力练习,看看它们是否能用sed解决这个难题——实际上,你不会在代码中使用由此产生的咒语
如果您的awk不支持\s
(gawk
支持),请将\s
更改为上面的[:space:]
。这可能对您有用(GNU-sed&Bash):
如前所述,遇到文件结尾时的n
命令将终止sed命令,因此在尝试读取另一行之前必须检查文件结尾
此sed解决方案使用保留空间收集记录,遇到新记录或文件结尾时,将保留空间替换为模式空间,删除换行符并添加额外的分隔线
使用bash变量$“…”
可以在一行解决方案中将sed命令分组在一起,但是另一种方法是使用-e
标志:
sed -e '/^\S/{$h:a;x;/./{s/\n//g;p;a\ ==========' -e '};x;h;d};H;$!d;ba' file
这可能适合您(GNU-sed&Bash):
如前所述,encouteri上的n
命令