我需要在新 macOS 上查找所有活动的网络接口。这意味着以下带有pcregrep
的单行代码将不起作用:
ifconfig | pcregrep -M -o '^[^t:]+(?=:([^n]|nt)*status: active)'
因为pcregrep
不是 macOS 上的默认安装。
我试图将其转化为egrep
但无济于事,因为积极的展望是不可能的,对吧?
所以我尝试在perl中使用单行代码。但是以下命令不起作用,因为交换机-pe
不会将所有行吞噬在一起。我也尝试过-p0e
。
ifconfig | perl -pe 'while (<>) {if (/^[^t:]+(?=:([^n]|nt)*status: active)/){print "$1";};}'
如果我以积极的展望搜索同一行,它正在工作;例如:
ifconfig | perl -pe 'while (<>) {if (/^([^t:]+)(?=:([^n]|nt)*mtu 1380)/){print "$1";};}'
utun0
ifconfig
的典型输出:
en10: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
options=6467<RXCSUM,TXCSUM,VLAN_MTU,TSO4,TSO6,CHANNEL_IO,PARTIAL_CSUM,ZEROINVERT_CSUM>
ether 00:e0:4c:68:01:20
inet6 fe80::1470:31b9:a01c:6f5e%en10 prefixlen 64 secured scopeid 0xd
inet 192.168.178.39 netmask 0xffffff00 broadcast 192.168.178.255
inet6 2003:ee:4f1a:ce00:864:f90c:9a11:6ad9 prefixlen 64 autoconf secured
inet6 2003:ee:4f1a:ce00:d89a:7e34:6dd4:1370 prefixlen 64 autoconf temporary
nd6 options=201<PERFORMNUD,DAD>
media: autoselect (1000baseT <full-duplex>)
status: active
预期结果将是:
en10
我使用的是macOS Monterey,zsh和perl 5.34
谢谢你的帮助
马立克
由于ifconfig
的输出正常†每个界面都有一个多行文本块,全部用空行分隔,因此在段落(-00)中阅读很方便。然后其余的简化了很多
ifconfig -a | perl -00 -nE'say $1 if /^(.+?)s*:.*?status:s+active/s'
我们仍然需要/s
修饰符,使.
匹配也成为换行符,因为每个段落本身就是一个多行字符串,并且模式需要跨多行匹配。
†除了它不在用于此问题的MacOS上 - 没有空行分隔接口块。 那么寻找段落是没有意义的(换行符不是),这个答案不适用于该系统。
下面是一个经典的逐行方法,该方法 - 在该接口输出的第一行设置接口名称(行首没有空格),然后测试活动状态
perl -wnE'$ifn=$1, next if /^(S[^:]+?)s*:/; say $ifn if /status:s+active/' file
这允许接口名称内有空格,这是非常不可能的(甚至可能不允许)。对于名称中不允许空格的限制性更强的模式,请使用/^(S+?)s*:/
(或更有效的/^([^:s]+)/
)。s*
和前面的?
只是为了使其不捕获尾随空格(就在:
之前),如果可能的话。
这也适用于接口块之间有空行的情况。
您可以使用
perl -0777 -nE 'say "$&" while /^[^nrt:]+(?=:(?:.*Rt)*status:h+active)/gm'
请参阅正则表达式测试。
在这里,-0777
对文件进行压缩,以便正则表达式可以匹配多行文本跨度(将换行符公开给pcregrap模式的M
等效项),say "$&"
打印所有匹配的子字符串(o
等效的子字符串,另请参阅g
标志)。
我编辑了[^t:]+
以匹配除制表符、冒号和 CR/LF 字符以外的任何一个或多个字符。此外,我将([^n]|nt)*
替换为更有效的(?:.*Rt)*
,该匹配除换行符以外的任何零个或多个字符的零个或多个出现,直到行尾 (.*
),然后是换行符序列 (R
),然后是制表符 (t
)。
另外,请注意m
标志^
以使锚点也匹配任何行起始位置。
perl 的 -n 和 -p 命令行开关在 -e 代码周围添加一个隐式的 while (<>) {...} 块,此外 -p 在每次迭代结束时打印该行。所以你需要将 -p 更改为 -n,只打印出匹配的行;并删除额外的和不需要的 while 循环。所以像
ifconfig | perl -ne 'print if /...../'