代码之家  ›  专栏  ›  技术社区  ›  comingstorm

为什么在regex模式中使用POSIX字符类会产生意想不到的结果?

  •  7
  • comingstorm  · 技术社区  · 14 年前

    我遇到了一些奇怪的Perl行为:在regexp中使用Posix字符类完全改变了结果字符串的排序顺序。

    sub namecmp($a,$b) {
      $a=~/([:alpha:]*)/;
      # $a=~/([a-z]*)/;
      $aword= $1;
    
      $b=~/([:alpha:]*)/;
      # $b=~/([a-z]*)/;
      $bword= $1;
      return $aword cmp $bword;
    };
    
    $_= <>;
    @names= sort namecmp split;
    print join(" ", @names), "\n";
    

    $test_normal
    aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cbb
    aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cbb
    
    $test_posix
    aaa aab aac aba abb abc aca acb acc baa bab bac bba bbb bbc bca bcb bcc caa cbb
    baa bab bac bba bbb bbc bca bcb bcc caa cbb aba abb abc aca acb acc aab aac aaa
    

    !" 是“好吧,别这样 ,然后!“。

    3 回复  |  直到 14 年前
        1
  •  13
  •   Sinan Ünür    14 年前

    角色类 [:alpha:] 表示Perl正则表达式中的alpha字符,但方括号表示 表示它们在正则表达式中通常所做的事情。所以你需要:

    $a=~/([[:alpha:]]*)/;
    

    perlre

    POSIX字符类语法

    [:class:]
    

    也可提供。请注意 [ ] 括号是文字;它们必须始终在字符类表达式中使用。

    # this is correct:
    $string =~ /[[:alpha:]]/;
    
    # this is not, and will generate a warning:
    $string =~ /[:alpha:]/;
    
        2
  •  8
  •   Sinan Ünür    14 年前

    你所写的不是想象中的Perl。你能逃脱惩罚是因为你已经关机了 warnings perl

    POSIX syntax [: :] belongs inside character classes in regex; marked by <-- HERE in m/([:alpha:] <-- HERE *)/ at j.pl line 4.

    POSIX syntax [: :] belongs inside character classes in regex; marked by <-- HERE in m/([:alpha:] <-- HERE *)/ at j.pl line 8.

    想象一下!

    现在, 也会告诉你:

    Illegal character in prototype for main::namecmp : $a,$b at j.pl line 3.

    use warnings; use strict;
    
    sub namecmp {
        my ($aword) = $a =~ /([[:alpha:]]*)/;
        my ($bword) = $b =~ /([[:alpha:]]*)/;
        return $aword cmp $bword;
    }
    
    print join(' ', sort namecmp split ' ', scalar <>), "\n";
    
        3
  •  6
  •   Community noseratio    7 年前

    因为Perl不支持这种形式的POSIX字符类(使用 [[:alpha:]] @Greg's answer )

    所以

    [:alpha:]
    

    被解释为由字符组成的字符类“ a h ", " l p “和” : ".

    [ahlp:] 一开始 (因为 * ),例如“ baa “匹配将返回一个空字符串。一个空字符串当然比其他字符串小,所以它们将被安排在开头。