Perl正则表达式将所有非浮点数替换为空格



我有一个字符串,我想替换所有不是x.x形式的浮点数,但每个浮点数之间仍然保持一个空格:

 my $substitute_this = "ABC123  5.4 6.2  9.7    3.8   7.3";
 my $substitution =  $substitute_this =~ s/(some regex)/(something else?)/gr;
 print $substitution; #5.4 6.2 9.7 3.8 7.3

我真的不知道如何做到这一点,我知道如何替换浮点数:

 s/[-+]?[0-9]+.[0-9]+//gr

我知道要在字符类中取消匹配我需要输入

[^0-9]

但是浮点数的正则表达式太长了,我不知道如何否定它。第二个问题是每个浮点数之间只有一个空格,我不知道如何完成。

我认为首先提取所有浮点数会更容易:

my @floats = $substitute_this =~ /(?<!S)([+-]?d+.d+)(?!S)/g;

,然后将它们连接成一个字符串:

print join(' ', @floats);

Edit:正如Jiri Klouda在下面指出的那样,这个浮点数的正则表达式相当简单,但它只是一个示例。如果你愿意,你可以调整它。关键是,这种方法让您颠倒了您试图做的逻辑,这样您就不必尝试匹配不是浮点数的任何内容(这很难),而只需匹配浮点数的任何内容。

该解决方案使用全局regex模式匹配来查找前面和后面都没有非空格字符的所有浮点数(可选的符号、数字、点、数字)。生成的列表简单地使用空格连接并返回到原始变量

我不知道你是否有任何其他格式的数字(例如,没有小数点),但你说"替换所有不是x.x形式的浮点数"所以这就是我所编码的,加上你后面提到的可选符号字符

use strict;
use warnings 'all';
use feature 'say';
my $s = "ABC123  5.4 6.2  9.7    3.8   7.3";
$s = join ' ', $s =~ / (?<!S) [+-]? d+ . d+ (?!S) /xg;
say $s;

输出
5.4 6.2 9.7 3.8 7.3

您可以使用map over list来解决这个问题:

sub extract_float {
  # split string with null char (s+)
  my @array = split(/s+/, shift);
  # anonymous function who return string only if 
  # arguments is in form `integer.integer`
  my $fun = sub { $_ =~ !d+.d+! };
  # map $fun on @array
  my @map = map(&$fun, @array);
  # convert @array in string (each value separated with space)
  join(" ", @map);
}
sub extract_float_oneline {
  join(" ", map({$_ =~ /(d+.d+)/} split(/s+/, shift)));
}
my $string = "ABC123  5.4 6.2  9.7    3.8   7.3";
print extract_float($string)."n";
# 5.4 6.2 9.7 3.8 7.3
print extract_float_oneline($string)."n";
# 5.4 6.2 9.7 3.8 7.3

作为@redneb解决方案的替代方案,一次性RegEx将是这样的:

d++.d++(?= +|Z)(*SKIP)(?!)|[^s]+ *|s(?=s)
Perl:

echo "5.23 ABC123  5.4 6.2965  9.7    3.8   7.3 5.3.3 ABC.2356" | perl -ne "s/d++.d++(?= +|Z)(*SKIP)(?!)|[^s]+ *|s(?=s)//g; print;"
输出:

5.23 5.4 6.2965 9.7 3.8 7.3 

实时演示(使用全局匹配并无替换)

最新更新