我正在编写一个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";
答案 0 :(得分:4)
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))) {
现在正在运作。