奇怪的Perl代码错误,退出0

时间:2014-04-18 13:14:29

标签: perl

我正在编写一个Perl代码,使用substr逐个提取字符,但遇到了一个非常奇怪的问题。

我正在尝试执行以下操作 逐个扫描字符,如果是#,则转到行尾,如果是'",则找到下一个匹配的字符。还添加了HTML颜色标记以突出显示它们。其他所有东西都打印出来。

这是代码块

while ($char = (substr $src, $off_set, 1)) {

  if ($char eq '#') {
    $end_index = index $src, "\n", $off_set+ 1;
    my $c = substr($src, $off_set, $end_index-$off_set+1);
    print $comment_color.$c.$color_end;
  } elsif (($char eq '"') || ($char eq "'")) {
    $end_index = index ($src, $char, $off_set+1);
    my $char_before = substr $src, $end_index-1, 1;

    while ($end_index > 0 && $char_before eq '\\') {
      $end_index = index $src, $char, $end_index + 1;
      $char_before = substr $src, $end_index-1, 1;
    }
    my $s = substr($src, $off_set, $end_index-$off_set+1);
    print $string_color.$s.$color_end;
  } else {
    print $char;
    $end_index++;
  }
    $off_set = $end_index + 1;
}

当我使用以下测试代码时,脚本将在第一个0退出,如果我删除所有0,那么它运行正常。如果我先移除0,它将在第二个退出。我真的不知道为什么会这样。

# Comment 1

my $zero = 0;
my @array = (0xdead_beef, 0377, 0b011011);
# xor
sub sample2
{
  print "true or false";
  return 3 + 4 eq " 7"; # true or false
}
   #now write input to STDOUT
print $time . "\n";
my $four = "4";

3 个答案:

答案 0 :(得分:4)

defined循环中检查while

while (defined(my $char = substr $src, $off_set, 1)) {

您的代码提前退出的原因是'0'是假值,因此while将结束。相反,这将检查是否从substr调用中提取了任何值。

答案 1 :(得分:3)

这是你的循环条件:

while ($char = (substr $src, $off_set, 1)) {
    ...

那么$char = "0"会发生什么?由于Perl认为这是一个假值,循环将终止。相反,只要剩下字符就循环:

while ($off_set < length $src) {
    my $char = substr $src, $off_set, 1;
    ...

无论如何,您的代码很复杂且难以阅读。请考虑使用正则表达式:

use re '/xsm';

my $src = ...;
pos($src) = 0;
my $out = '';
while (pos($src) < length $src) {
    if ($src =~ m/\G ([#][^\n]*)/gc) {
        $out .= colored(comment => $1);
    }
    elsif ($src =~ m/\G (["] (?:[^"\\]++|[\\].)* ["])/gc) {
        $out .= colored(string => $1);
    }
    elsif ($src =~ m/\G (['] (?:[^'\\]++|[\\]['\\])* ['])/gc) {
        $out .= colored(string => $1);
    }
    elsif ($src =~ m/\G ([^"'#]+)/gc) {
        $out .= $1;
    }
    else {
        die "illegal state";
    }
}

其中colored是一些辅助函数。

答案 2 :(得分:0)

最后,想通了它是while循环。它在看到0时退出循环。

while循环条件更新为

while (($char = (substr $src, $off_set, 1)) || ($off_set < (length $src))) {

现在正在运作。