我有一个字符串,我想替换所有不是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
实时演示(使用全局匹配并无替换)