问题描述
|
我正在尝试捕获传感器的温度输出,为此我有以下几行内容:
temp1: +39.5 C (crit = +105.0 C)
Core 0: +40.0 C (high = +100.0 C,crit = +100.0 C)
Core 1: +40.0 C (high = +100.0 C,crit = +100.0 C)
我只需要每行的第一个温度(39.5、40.0、40.0)。当然,问题在于我无法真正使用单词编号,因为\“ Core 0 \” / \“ Core 1 \”中有多余的空格。
我想出了以下有效的正则表达式,但是有人告诉我,使用.*
是对正则表达式的一种懒惰和肮脏的方法。
$core_data =~ s/^.*\\+(.*)C\\ .*$/$1/g;
我想知道,是否有更严格或更完善的方法来完成此任务,或者我做得好吗?
解决方法
更简洁的正则表达式
/\\+(\\d+\\.?\\d*) C/
这将使第一个温度与可选的十进制值匹配。
#!/usr/bin/perl
use strict;
use warnings;
my $re = qr{\\+(\\d+\\.?\\d*) C};
while (my $line = <DATA>){
$line =~$re and print $1,\"\\n\";
}
__DATA__
temp1: +39.5 C (crit = +105.0 C)
Core 0: +40.0 C (high = +100.0 C,crit = +100.0 C)
Core 1: +40.0 C (high = +100.0 C,crit = +100.0 C)
输出:
39.5
40.0
40.0
, 我不明白您为什么要搜索并用正则表达式(ѭ6replace)替换,如果您只是想捕获第一个温度。您的正则表达式似乎依赖于.*
的贪婪。假设您可以依赖name: temp C (...
格式,则此正则表达式将可以运行而不必匹配整个字符串:
$core_data =~ m/^(?:\\w*\\b)*:\\s*(\\+?\\d+\\.\\d+)/;
...或在前面没有+的情况下捕获:
$core_data =~ m/^(?:\\w*\\b)*:\\s*\\+?(\\d+\\.\\d+)/;
, 更精确的正则表达式
$core_data =~ s/^.*\\+([\\d.]+ )C\\ .*$/$1/g;
但是下面的内容可能就足够了,因为似乎只有数值值很有趣。
$cpu_head = $1 if m/:\\s*\\+([\\d.]+) C/;
注意:\\ s代表任何空格,\\ d代表任何数字。
, 恕我直言,。*很有用,尽管当您可以将其缩小到更具体的范围时,情况会更好。
就您而言,您可以说
S/^[^+]+\\+([0-9.]) C.*$/$1/g
在此正则表达式中,我专注于我要寻找的内容,并将温度表征为一个数字序列,其某个点处有一个点,而其余部分与我无关。由于每行中有两个温度,而您只想要第一个温度,因此我在开头使用了[^ +],它匹配所有非+的温度,因此它将在第一个温度开始的地方停止。达到温度后,我便使用。*吞噬了所有内容,直到行尾为止。
这只是推理的一个例子,它并不假装您可以提出解决问题的最佳正则表达式。
, 这看起来比regex更适合ѭ14。 split
将自动清除所有不必要的空格,并且您无需为数据更改而事先计划。
my $tag;
($tag,$core_data) = split (/:/,$core_data);
my @fields = split (/\\s/,$core_data);
my $temp = $fields[0];
我相信,这会将字符串\"+39.5\"
和\"+40.0\"
存储在不同的示例行中,可以自动将其转换为数字。
另外,您将可以轻松访问$tag
中的行标签。
如果需要,可以使用正则表达式在括号内截断添加的信息:
if ($core_data =~ s/\\(([^\\)]*)\\)//) {
my $tmp = $1;
$tmp =~ s/[\\s\\+C]//g; # clear away junk
%data = split (/=/,(split (/,/,$tmp)));
}
for my $key (keys %data) {
printf \"%-7s = %s\\n\",$key,$data{$key};
}
, 我会编写一个通用函数来解析输入并返回哈希值。一般来说,我会使用此正则表达式:
m/\\A ([^:]+) : \\s+ ([+-][0-9.]+) /xms
这匹配一行。 $ 1是匹配项(即\“ Core 0 \”),$ 2是匹配项。我也将进行从字符串到数字的转换,并以这样的结尾:
my $temp_string = q{
temp1: +39.5 C (crit = +105.0 C)
Core 0: +40.0 C (high = +100.0 C,crit = +100.0 C)
Core 2: -40.0 C (high = +100.0 C,crit = +100.0 C)
};
my $temps = parse_temps($temp_string);
print \"temp1: \",$temps->{temp1},\"\\n\";
print \"Core 0: \",$temps->{core0},\"\\n\";
print \"Core 1: \",$temps->{core1},\"\\n\";
print \"Core 2: \",$temps->{core2},\"\\n\";
sub parse_temps {
my ( $str ) = @_;
my %temp;
for my $line ( split /\\n/,$str ) {
if ( $line =~ m/\\A ([^:]+) : \\s+ ([+-][0-9.]+) /xms ) {
my $key = $1;
my $value = $2;
$key =~ s/\\s+//g;
$temp{ lc $key } = 0+$value;
}
}
return wantarray ? %temp : \\%temp;
}
程序的输出:
temp1: 39.5
Core 0: 40
Core 1: 40
Core 2: -40