【问题标题】:Arithmetic Calculation in Perl Substitute Pattern MatchingPerl 替代模式匹配中的算术计算
【发布时间】:2014-09-04 22:20:35
【问题描述】:

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

【问题讨论】:

  • 这是作业吗?
  • "comment: ..." 当然,它实际上加起来是 38。
  • 没有。实际上,这将帮助我开始了解如何在 Perl 的正则表达式中进行算术计算。
  • 你考虑过this perldoc吗?
  • 感谢该来源。我只是略过它。实际上,我在网上搜索了一种可行的方法,但没有成功。不幸的是,在您提到的 perldoc 中,我看到了嵌入代码部分,但我不知道如何引用匹配字符串中的每个字符以便能够对其进行计算。

标签: regex perl


【解决方案1】:

我想我会把这个作为答案发布,尽管提出这个想法的功劳应该归于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 修饰符将匹配重置为字符串的开头。

【讨论】:

    【解决方案2】:

    只需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
    

    【讨论】:

      【解决方案3】:

      您可以在替换中使用/e 修饰符吗?

      $s = "ABCDMNA";
      $s =~ s/(.)/$S += ord($1) - ord "@"; 1 + pos $s == length $s ? $S : ""/ge;
      print "$s\n"
      

      【讨论】:

        【解决方案4】:

        考虑以下匹配场景:

        my $text = "ABCDMNA";
        my $val = $text ~= s!(\d)*([A-Z])!($1+ord($2)-ord('A')+1)!gr;
        

        (未经测试...)这应该反复遍历字符串,一次替换一个字符,并将其序数值添加到已放在开头的当前总和中。一旦没有更多字符,副本 (/r) 将被放置在应包含已翻译值的 $val 中。

        【讨论】:

        • 这是一个很好的努力,虽然这不起作用。您需要一种方法来重置比赛的位置。我做了perl -ple'1 while s/(\d*)([A-Z])/$1+ord($2)-64/e',这会将正则表达式匹配重置为每个新匹配的开始,直到所有字母都被消耗完。
        • 嗯...我认为/g 会一直这样重复,哦,好吧
        • 我会把这个答案留在这里以补充你的@TLP。
        • 这个想法+1。是的,/g 可以工作,如果可以将活动位置设置为数字之前。我尝试使用pos,但它似乎不起作用,所以这是更简单的选择。
        【解决方案5】:

        或者一个简短的替代方案:

        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 打印 sum 的值

        来自perlre

        (?{ 代码 })

        这个零宽度断言执行任何嵌入的 Perl 代码。它总是 成功,返回值为 $^R 。

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2017-03-02
          • 1970-01-01
          • 1970-01-01
          • 2014-08-20
          • 2013-12-23
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多