首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Perl正则表达式解析lshw的输出?

如何使用Perl正则表达式解析lshw的输出?
EN

Stack Overflow用户
提问于 2018-04-13 19:34:01
回答 3查看 175关注 0票数 0

我正在尝试用这段代码将lshw输出解析成一个哈希值,到目前为止还行得通。

代码语言:javascript
复制
  use strict;
  use warnings;

  my (%lshw,$key,$value);
  while (<>){
  s/#.*//;                # no comments
  s/^\s+//;               # no leading whites
  s/\s+$//;               # no trailing whites
  next unless length;     # anything left?
  if (/(?<key>.*?):\s+(?<value>.*)/x){
    $lshw{$+{key}} = $+{value};
  }
}

# remove white spaces in hash keys
for $key (keys %lshw){
  $value = delete $lshw{$key};
  for ($key){
    s/\s+//g;
   }
  $lshw{$key} = $value;
  }

my $logname   = $lshw{'logicalname'};
print "Logical name\t $logname\n";

但当我遇到这样的配置时,我会感到困惑:

代码语言:javascript
复制
clock: 33Mhz 
width: 32 bits 
capacity: 1Gbit/s 
configuration:autonegotiation=on broadcast=yes driver=igb driverversion=5.3.0-k duplex=full firmware=1.63, 0x800009fa ip=[REMOVED] latency=0 link=yes multicast=yes port=twisted pair speed=1Gbit/s`

我尝试了一种hoh方法,但没有找到如何拆分键/值的解决方案,因为它包含像port=twisted pair这样的多字值。关键始终是一个单词。

谁能给我一个提示如何解决这个问题?

(感谢simbabque的严格/警告提示)

EN

回答 3

Stack Overflow用户

发布于 2018-04-13 21:39:57

您需要的是捕获等号后面的所有字符,这些字符后面没有模式somekeyname=

代码语言:javascript
复制
#!/usr/bin/env perl

use strict;
use warnings;

my $s = q{configuration: autonegotiation=on broadcast=yes driver=igb driverversion=5.3.0-k duplex=full firmware=1.63, 0x800009fa ip=[REMOVED] latency=0 link=yes multicast=yes port=twisted pair speed=1Gbit/s};

my ($key, $rest) = split /:\s*/, $s, 2;

my %params = ($rest =~ / (\w+) = ((?:. (?! \w+ = ))+) /gx);

use YAML::XS;
print Dump \%params;

输出:

代码语言:javascript
复制
---
autonegotiation: on
broadcast: yes
driver: igb
driverversion: 5.3.0-k
duplex: full
firmware: 1.63, 0x800009fa
ip: '[REMOVED]'
latency: '0'
link: yes
multicast: yes
port: twisted pair
speed: 1Gbit/s

此外,还可以改进您的初始循环:

代码语言:javascript
复制
 while (<>) {
     next if /^#/; # skip comments
     /\S/ or next; # skip blank lines
     s/^\s+//;
     s/\s+\z//;
     # ...
}
票数 4
EN

Stack Overflow用户

发布于 2018-04-13 21:56:33

您只需按如下方式split配置字符串

代码语言:javascript
复制
use strict;
use warnings 'all';
use feature 'say';

my $s = 'configuration: autonegotiation=on broadcast=yes driver=igb driverversion=5.3.0-k duplex=full firmware=1.63, 0x800009fa ip=[REMOVED] latency=0 link=yes multicast=yes port=twisted pair speed=1Gbit/s';

say for split /\s+(?=[^\s=]+=)/, $s;

输出

代码语言:javascript
复制
configuration:
autonegotiation=on
broadcast=yes
driver=igb
driverversion=5.3.0-k
duplex=full
firmware=1.63, 0x800009fa
ip=[REMOVED]
latency=0
link=yes
multicast=yes
port=twisted pair
speed=1Gbit/s

现在,您就有了一个键及其值的列表,该列表由键名称正确划分。这应该是易于处理的

票数 1
EN

Stack Overflow用户

发布于 2018-04-13 22:57:47

Borodin的方法就是它。

如果您想用regexp解析它,这将会起作用,并将键与它的值分开。

代码语言:javascript
复制
#!/usr/bin/env perl

use warnings FATAL => 'all';
use strict;
my $s = 'configuration: autonegotiation=on broadcast=yes driver=igb driverversion=5.3.0-k duplex=full firmware=1.63, 0x800009fa ip=[REMOVED] latency=0 link=yes multicast=yes port=twisted pair speed=1Gbit/s';

while ($s =~ m/(?<key>[A-Za-z0-9]+)=(?<value>([\/\[\]A-Za-z0-9., -]+)(?= [a-z]+)|([\/\[\]A-Za-z0-9., -]+))/g) {
    print "$+{key} >>  $+{value}\n";
    $s =~ s/$+{key}//;
}

输出

代码语言:javascript
复制
autonegotiation >>  on
broadcast >>  yes
driver >>  igb
driverversion >>  5.3.0-k
duplex >>  full
firmware >>  1.63, 0x800009fa
ip >>  [REMOVED]
latency >>  0
link >>  yes
multicast >>  yes
port >>  twisted pair
speed >>  1Gbit/s

Pros

  • 键/值分离

Cons

正则表达式中的

  • 开销很大的正向先行

重构提案

消除正则表达式[\/\[\]A-Za-z0-9., -]

  • get中的复杂字符组
  • 替换循环

中找到的模式

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49816050

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档