Perl:这是好的还是不好的正则表达式,以及如何改进它?

问题描述

| 我正在尝试捕获传感器的温度输出,为此我有以下几行内容:
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
    

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...