只使用一个 Perl替换正则表达式语句(s///
),我们如何写下面的内容:
每个成功匹配只包含一串字母字符A..Z
。我们需要用匹配字符串替换匹配字符串,该替换将是匹配字符串中每个字符的字符索引(按字母顺序排列)的总和。
注意:对于A,字符索引为1,对于B,2 ...而对于Z,则为26。
请参阅以下示例:
success match: ABCDMNA
substitution result: 38
注意:
1 + 2 + 3 + 4 + 13 + 14 + 1 = 38;
自
A = 1, B = 2, C = 3, D = 4, M = 13, N = 14 and A = 1.
答案 0 :(得分:5)
我想将此作为答案发布,我想,虽然提出这个想法的功劳应该归abiessu提出his answer中提出的想法。
perl -ple'1 while s/(\d*)([A-Z])/$1+ord($2)-64/e'
由于这显然是家庭作业和/或学术兴趣,我将在剧透标签中发布解释。
- 我们匹配可选号码
(\d*)
,后跟字母([A-Z])
。数字是运行总和,字母是我们需要添加到总和中的字母 - 通过使用/e
修饰符,我们可以进行数学计算,即将捕获的数字添加到捕获的字母的ord()
值减去64.返回并插入总和而不是数字和这封信 - 我们使用while
循环进行冲洗并重复,直到所有字母都被替换,剩下的所有字母都是数字。我们使用while循环而不是/g
修饰符将匹配重置为字符串的开头。
答案 1 :(得分:3)
use strict;
use warnings;
use List::Util qw(sum);
my $string = 'ABCDMNA';
my $sum = sum map {ord($_) - ord('A') + 1} split //, $string;
print $sum, "\n";
输出:
38
答案 2 :(得分:2)
您可以在替换中使用/e
修饰符吗?
$s = "ABCDMNA";
$s =~ s/(.)/$S += ord($1) - ord "@"; 1 + pos $s == length $s ? $S : ""/ge;
print "$s\n"
答案 3 :(得分:2)
考虑以下匹配方案:
my $text = "ABCDMNA";
my $val = $text ~= s!(\d)*([A-Z])!($1+ord($2)-ord('A')+1)!gr;
(没有测试过它......)这应该反复遍历字符串,一次替换一个字符,其序号值加到已经放在开头的当前总和。一旦没有其他字符,副本(/r
)就会放在$val
中,其中应包含已翻译的值。
答案 4 :(得分:0)
或者简短的替代方案:
echo ABCDMNA | perl -nlE 'm/(.)(?{$s+=-64+ord$1})(?!)/;say$s'
或可读
$s = "ABCDMNA";
$s =~ m/(.)(?{ $sum += ord($1) - ord('A')+1 })(?!)/;
print "$sum\n";
打印
38
说明:
any character
“空正则表达式”后面不能跟的内容。 /.(?!)/
/(.)(?!)/
(?{...})
运行perl代码,将$1
say $s
打印和的值来自perlre
(?{code})
这个零宽度断言执行任何嵌入的Perl代码。它永远 成功,其返回值设置为$ ^ R。
警告:安全使用此功能需要您了解它 限制。执行的具有副作用的代码可能无法执行 由于未来的影响,从版本到版本完全相同 正则表达式引擎中的优化。有关这方面的更多信息,请参阅 嵌入式代码执行频率。