用Perl标记逗号

时间:2018-01-03 15:07:02

标签: regex perl

请从this code解释这两行Perl。

# separate out "," except if within numbers (5,300)
# previous "global" application skips some:  A,B,C,D,E > A , B,C , D,E
# first application uses up B so rule can't see B,C
# two-step version here may create extra spaces but these are removed later
# will also space digit,letter or letter,digit forms (redundant with next section)
$text =~ s/([^\p{IsN}])[,]/$1 , /g;
$text =~ s/[,]([^\p{IsN}])/ , $1/g;

2 个答案:

答案 0 :(得分:4)

您的代码会进行两次替换。 ubuntu是替换,s///标志告诉它全局,基本上替换所有

两行都使用正则表达式中的\p{} unicode property character groups。使用/g,它会检查字符是否为数字。

IsN

它取代了捕获的非数字,空格,逗号和空格。

第二行也是如此,但首先使用逗号。

您可以使用相同的功能将此代码重写为更短,更简洁。 / ( # capture group [ # character group ^ # not the following characters \p{IsN} # all characters that are a number ] ) [,] # followed by a comma / 所有没有此属性的字符,这样就无需\P{}。这可以进一步缩短到[]

\PN

答案 1 :(得分:2)

  1. 将所有逗号前面的逗号替换为不具有“{Number”Unicode常规类别的字符␠,␠
  2. 将所有逗号后跟一个没有“Number”Unicode General Category的字符替换为␠,␠
  3. 嗯,不太好。因为逗号本身是一个非数字字符,所以上面没有准确描述当一行中有两个逗号时会发生什么。

    但是,由于A,B变为A␠␠,␠␠B,因此效果不佳,所以不值得详细说明。

    标记生成器:

    my @tokens;
    for ($text) {
       if (/\G ( (?: [^,\d]++ | \d(?:,\d++)*+ )++ ) /xgc) {
          push @tokens, [ TEXT => $1 ];
          redo;
       }
    
       if (/\G , /xgc) {
          push @tokens, [ 'COMMA' ];
          redo;
       }
    
       if (/\G \z /xgc) {
          push @tokens, [ 'EOF' ];
          last;
       }
    
       die("Internal error\n");
    }