【问题标题】:Regex for parsing with newline character使用换行符解析的正则表达式
【发布时间】:2020-09-11 12:31:24
【问题描述】:

我正在尝试调试一个 perl 脚本来解析包含 IPv6 地址和端口详细信息的表上的 snmpwalk 输出。

snmpwalk命令在shell上的执行结果如下:

[root@newton log]# /usr/bin/snmpwalk -v 2c -c secret localhost  SNMP-TARGET-MIB::snmpTargetAddrTAddress
SNMP-TARGET-MIB::snmpTargetAddrTAddress.'2' = Hex-STRING: FD 22 1A 16 0E D3 01 00 00 00 00 00 00 10 00 41 
00 A2

perl 脚本尝试获取 snmpTargetAddrTAddress. 之后的值 -> 即 2,然后尝试获取 Hex-STRING 之后的值。它在代码中使用以下正则表达式

@buf   = `$snmpwalk $address_oid`;
foreach (@buf) {
      if (/snmpTargetAddrTAddress\.'(.+?)' = Hex-STRING: ([\w ]+)/)
             my $name = $1;
             my $rest= $2;
             log_msg( LOG_CRIT, "Found IP $rest for $name" );
      }

$1 等于2

$2 等于 FD 22 1A 16 0E D3 01 00 00 00 00 00 00 10 00 41

但我也需要出现在 shell 换行符中的值 00 A2

我尝试了在线工具 - https://regex101.com/。它提供的正则表达式为 ([\w ]+)(\n[\w ]+)。但是在代码中使用时,我没有得到任何输出。

以下不输出任何内容

if (/snmpTargetAddrTAddress\.'(.+?)' = Hex-STRING: ([\w ]+)(\n[\w ]+)/

我做错了什么?在线工具中的上述表达式会产生结果。如果我需要在 shell 输出中获取出现在换行符中的字符,我还可以使用哪些其他正则表达式?

@GMB 建议后的代码:

if(/snmpTargetAddrTAddress\.'(.+?)' = Hex-STRING: ([\w\s\n]+)/) {
        my $name = $1;
        my $rest = $2;
        log_msg( LOG_CRIT, "Found IP $rest for $name" );
 }

看到的日志是: " Found IP FD 22 1A 16 0E D3 01 00 00 00 00 00 00 10 00 41 for 2"

更新:根据来自@zdim 和@ikegami 的cmets,我错误地假设“00 A2”将成为第二次迭代本身的一部分。由于它们出现在第三行,因此它们出现在 foreach 的第三次迭代中

【问题讨论】:

  • 展示你如何得到这个字符串会很有帮助......你是否有机会在反引号下运行命令(并分配给一个标量)? (那些00 A2 真的用这个命令在单独的一行出现吗?)
  • 重新更新,您正在匹配 $_。它实际上包含整个文本还是仅包含第一行?
  • conf_params.trap_target_ip6 @zdim,ikegami。我的错 。在不检查 $_.这似乎不包含整个文本。我已经更新了描述中的代码。我在运行命令后使用foreach。在循环的第三次迭代中可以看到“00 A2”!。
  • 好吧,这样更好。那么,@buff 中有什么,你能证明一下吗?什么“第三次迭代”——问题开头显示的在 shell 中运行的示例,总共显示了两行?
  • 如果想要的 "rest" 确实是输出中的所有其余部分,那么您可以分配给一个标量 (my $ret = qx(...);),在这种情况下,反引号返回一个多行字符串,然后使用 GMB 的答案。 (或者加入行 my $ret = join '', @buff; 并在上面使用它。)

标签: regex string perl


【解决方案1】:

为什么不简单地将换行符添加到允许的字符列表中呢?实际上,正如zdim 所评论的,\s 匹配空格和换行符,所以你可以这样做:

/snmpTargetAddrTAddress\.'(.+?)' = Hex-STRING: ([\w\s]+)/

如果需要,您可以将其从解析值中删除:

use strict;
use warnings;

my $str = qq/SNMP-TARGET-MIB::snmpTargetAddrTAddress.'2' = Hex-STRING: FD 22 1A 16 0E D3 01 00 00 00 00 00 00 10 00 41\n00 A2/;
if (my ($addr, $hex) =  ($str =~ /snmpTargetAddrTAddress\.'(.+?)' = Hex-STRING: ([\w\s]+)/)) {
    $hex =~  s/\n/ /; 
    print "addr: $addr\nhex: $hex\n"
}

产量:

addr: 2
hex: FD 22 1A 16 0E D3 01 00 00 00 00 00 00 10 00 41 00 A2

【讨论】:

  • 感谢您的回复。我试过你的解决方案。不知何故,我的代码没有给出结果。我在我的问题中发布了更多我的代码。
  • 我想,我需要删除换行符,然后打印到log_msg?
  • @Prabhu 有一个错字(正则表达式中= 之前缺少空格),我刚刚修复了它——再试一次。 (我还添加了一个空格而不是\n,之前只是删除了)
  • @zdim:感谢您纠正我的错别字(我在从终端复制时弄混了……)!并感谢 \n\s 的提示 - 我相应地更新了我的答案。
【解决方案2】:

试试Hex-STRING:\s+([a-fA-F0-9]{2}(?:\s*[a-fA-F0-9]{2})*)
对于那部分

demo

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    • 2012-07-08
    • 1970-01-01
    相关资源
    最近更新 更多