gpt4 book ai didi

linux - 使用 grep 仅打印匹配项的一部分

转载 作者:IT王子 更新时间:2023-10-29 00:34:50 30 4
gpt4 key购买 nike

我很感兴趣是否可以在以下情况下使用单个 grep 命令。

我有一个 dhcpd.conf 文件,其中定义了 DHCP 主机。给定主机名,我需要在 dhcpd.conf 文件中找到它的 MAC 地址。我需要使用它来禁用它的 PXE 启动配置,但这不是这个问题的一部分。

文件的语法是统一的,但我还是想让它更简单一些。以下是主机的定义方式:

    host client1 { hardware ethernet 12:23:34:56:78:89; fixed-address 192.168.1.11; filename "pxelinux.0"; }
host client2 { hardware ethernet 23:34:45:56:67:78; fixed-address 192.168.1.12; filename "pxelinux.0"; }
host client3 { hardware ethernet AB:CD:EF:01:23:45; fixed-address 192.168.1.13; filename "pxelinux.0"; }
host client4 { hardware ethernet C1:CA:88:FA:F4:90; fixed-address 192.168.1.14; filename "pxelinux.0"; }

我们假设所有配置只需要一行,即使 dhcpd.conf 语法允许将选项分成多行。但是,我们假设选项的顺序可能不同。

我想到了以下 grep 命令:

grep -o "^[^#]*host.*${DHCP_HOSTNAME}.*hardware ethernet.*..:..:..:..:..:..;" /etc/dhcp/dhcpd-hosts.conf

它应该忽略那些被注释的行,允许 token 之间的任意空格,并且匹配直到 MAC 地址的末尾。当我运行它时,我得到这样的行:

host client1 { hardware ethernet 12:23:34:56:78:89;

这太棒了!不过关键是我只需要一个MAC地址,不需要前面的垃圾。现在我知道使用另一个 grep、cut 或 awk 从这个输出中只剪切 MAC 地址是微不足道的。但我想知道,有没有一种方法可以使用单个 grep 命令来获得最终结果,而不必将此输出通过管道传输到另一个过滤器?显然我不能省略模式的开头,因为我想获得一个特定的主机名,从而匹配 "..:..:..:..:..:.. "会给我所有的 MAC 地址。

再一次,我想要一个命令(不一定是 grep),它只从文件中删除正确的 MAC 地址。因此,我对那些说“grep ... | grep ...”或“grep ... | cut ...”等的解决方案不感兴趣。

当然,在实践中,如果我使用多个过滤器并将它们通过管道传输,并没有什么不好的事情发生,我只是好奇是否可以用一个过滤器来解决。

我会将输出分配给一个变量。

最佳答案

您可以使用 Perl 单行代码将文件的每一行与具有适当捕获组的单个正则表达式进行匹配,并且对于匹配的每一行,您可以打印子匹配项。

有几种方法可以使用 Perl 来完成这项任务。我建议使用 perl -ne {program}惯用语,它隐式循环 stdin 的行并执行一行 {program}每行一次,当前行作为 $_ 可用特殊变量。 (注意:-n 选项不会导致 $_ 的最终值在隐式循环的每次迭代结束时自动打印,这正是 -p 选项会做的; 即 perl -pe {program} .)

解决方法如下。请注意,我决定使用晦涩难懂的 -s 来传递目标主机名。选项,它可以在 {program} 之后解析变量赋值规范参数,类似于 awk 的 -v选项。 (无法使用 -n 选项传递普通的命令行参数,因为隐式 while (<>) { ... } 循环吞噬了文件名的所有此类参数,但 -s 机制提供了一个很好的解决方案。参见 Is it possible to pass command-line arguments to @ARGV when using the -n or -p options? 。 ) 这种设计避免了嵌入 $DHCP_HOSTNAME 的需要{program} 中的变量字符串本身,这允许我们将其单引号并保存一些(实际上是 8 个)反斜杠。

DHCP_HOSTNAME='client3';
perl -nse 'print($1) if m(^\s*host\s*$host\s*\{.*\bhardware\s*ethernet\s*(..:..:..:..:..:..));' -- -host="$DHCP_HOSTNAME" <dhcpd.cfg;
## AB:CD:EF:01:23:45

sed 相比,我更喜欢 Perl原因如下:

  • Perl 提供了一个完整的通用编程环境,而 sed更有限。
  • Perl 在 CPAN 上有一个巨大的公开模块库可以轻松安装,然后与 -M{module} 一起使用选项。 sed不可扩展。
  • Perl 拥有比 sed 更强大的正则表达式引擎,具有环视断言、回溯控制动词、内部正则表达式和替换 Perl 代码、更多选项和特殊转义、嵌入式组选项等。参见 perlre .
  • 与直觉相反,尽管 Perl 更复杂,但它通常比 sed 快得多。由于其两遍过程和高度优化的操作码实现。参见 http://rc3.org/2014/08/28/surprisingly-perl-outperforms-sed-and-awk/例如。
  • 我经常发现等效的 Perl 实现比 sed 的实现更直观。 , 自 sed有一组更原始的命令来操作底层文本。

关于linux - 使用 grep 仅打印匹配项的一部分,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39231566/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com