0

我正在尝试在 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)%/',
  '.'
]

做这个的最好方式是什么?

4

1 回答 1

2

(?:(?!STRING).)*is to STRINGas [^CHAR]*is to 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将为您提供有关错误发生位置的信息。

于 2013-03-18T08:59:31.897 回答