请从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;
您的代码会进行两次替换。 s///
是一个替换,/g
标志告诉它在全球范围内进行,基本上是替换所有。
两行都在正则表达式中使用\p{}
unicode property character groups。使用IsN
,它会检查字符是否为数字。
/
( # capture group
[ # character group
^ # not the following characters
\p{IsN} # all characters that are a number
]
)
[,] # followed by a comma
/
它取代了捕获的不是数字,空格,逗号和空格。
第二行也是如此,但首先是逗号。
您可以使用相同的功能将此代码重写为更短,更简洁。 \P{}
是所有没有这个属性的字符,这消除了对[]
的需要。这可以进一步缩短到\PN
。
$text =~ s/(\PN),/$1 , /g;
$text =~ s/,(\PN)/ , $1/g;
␠,␠
替换前面没有“Number”Unicode General Category的字符的所有逗号。␠,␠
替换所有逗号,后跟一个没有“Number”Unicode General Category的字符。嗯,不太好。因为逗号本身是非数字字符,所以上面没有准确描述当一行中有两个逗号时会发生什么。
但是,由于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");
}