我正在尝试用这段代码将lshw输出解析成一个哈希值,到目前为止还行得通。
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";但当我遇到这样的配置时,我会感到困惑:
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的严格/警告提示)
发布于 2018-04-13 21:39:57
您需要的是捕获等号后面的所有字符,这些字符后面没有模式somekeyname=。
#!/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;输出:
---
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 (<>) {
next if /^#/; # skip comments
/\S/ or next; # skip blank lines
s/^\s+//;
s/\s+\z//;
# ...
}发布于 2018-04-13 21:56:33
您只需按如下方式split配置字符串
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;输出
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现在,您就有了一个键及其值的列表,该列表由键名称正确划分。这应该是易于处理的
发布于 2018-04-13 22:57:47
Borodin的方法就是它。
如果您想用regexp解析它,这将会起作用,并将键与它的值分开。
#!/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}//;
}输出
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/sPros
Cons
正则表达式中的
重构提案
消除正则表达式[\/\[\]A-Za-z0-9., -]
中找到的模式
https://stackoverflow.com/questions/49816050
复制相似问题