用于正则表达式令牌的perl流文件,包括扫描的令牌

时间:2013-03-18 08:54:11

标签: regex perl tokenize

我正在尝试在perl中传输文件并对行进行标记并包含标记。

我有:

while( $line =~ /([\/][\d]*[%].*?[%][\d]*[\/]|[^\s]+|[\s]+)/g ) {
  my $word = $1;
  #...
}

但是当令牌中没有空格时它不起作用。

例如,如果我的行是:

$line = '/15%one (1)(2)%15/ is a /%good (1)%/ +/%number(2)%/.'

我想把这一行分成:

$output =
[
  '/15%one (1)(2)%15/',
  ' ',
  'is',
  ' ',
  'a',
  '/%good (1)%/',
  ' ',
  '+',
  '/%number(2)%/',
  '.'
]

这样做的最佳方式是什么?

1 个答案:

答案 0 :(得分:2)

(?:(?!STRING).)*STRING[^CHAR]*CHAR,所以

my @tokens;
push @tokens, $1
   while $line =~ m{
      \G
      ( \s+
      | ([\/])([0-9]*)%
        (?: (?! %\3\2 ). )*
        %\3\2
      | (?: (?! [\/][0-9]*% )\S )+
      )
   }sxg;

但这不会验证。如果要验证,可以使用

my @tokens;
push @tokens, $1
   while $line =~ m{
      \G
      ( \s+
      | ([\/])([0-9]*)%
        (?: (?! %\3\2 ). )*
        %\3\2
      | (?: (?! [\/][0-9]*% )\S )+
      | \z (*COMMIT) (*FAIL)
      | (?{ die "Syntax error" })
      )
   }sxg;

以下内容也经过验证,但它更具可读性,可以轻松区分令牌类型。:

my @tokens;
for ($line) {
   m{\G ( \s+ ) }sxgc
      && do { push @tokens, $1; redo };

   m{\G ( ([\/])([0-9]*)%  (?: (?! %\3\2 ). )*  %\3\2 ) }sxgc
      && do { push @tokens, $1; redo };

   m{\G ( (?: (?! [\/][0-9]*% )\S )+ ) }sxgc
      && do { push @tokens, $1; redo };

   m{\G \z }sxgc
      && last;

   die "Syntax error";
}

pos将为您提供有关错误发生位置的信息。