将 pcregrep 翻译成 Perl 单行



我需要在新 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 /...../'

相关内容

  • 没有找到相关文章

最新更新