Perl替换模式匹配中的算法计算

时间:2014-09-04 22:20:36

标签: regex perl

只使用一个 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.

5 个答案:

答案 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)

只需split,翻译和sum

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。

     

警告:安全使用此功能需要您了解它   限制。执行的具有副作用的代码可能无法执行   由于未来的影响,从版本到版本完全相同   正则表达式引擎中的优化。有关这方面的更多信息,请参阅   嵌入式代码执行频率。