如果要打印第 2、6、10 行,则:
while (<>)
{
print if $. % 4 == 2;
}
当前行号在哪里$.
——我没有花时间打开和关闭文件。那可能是:
{
my $file = "file1.txt";
open my $in, "<", $file or die "cannot open input file $file: $!";
while (<$in>)
{
print if $. % 4 == 2;
}
}
这使用了现代首选形式的文件句柄(词法文件句柄),结构周围的大括号表示文件句柄自动关闭。无法打开的文件名包含在错误消息中;使用了or
运算符,因此优先级是正确的(括号和||
原文中的也很好,可以在这里使用,但通常不是)。
如果您希望一行以 print 开头@
,则必须以不同的方式组织事物。
my $print_next = 0;
while (<>)
{
if ($print_next)
{
print $_;
$print_next = 0;
}
elsif (m/^@/)
{
$print_next = 1;
}
}
剖析问题中的代码
问题中代码的原始版本是(为方便起见添加了行号):
1 open(IN,"<", "file1.txt") || die "cannot open input file:$!";
2 while (<IN>) {
3 $line = $line . $_;
4 if ($line =~ /^\@/) {
5 <IN>;
6 #next;
7 my $line = $line;
8 }
9 }
10 print "$line";
每一行的讨论:
- 好的,尽管它不使用词法文件句柄或报告无法打开的文件。
- 好的。
- 过早和误导。
$line
这会在任何分析完成之前将当前行添加到变量中。如果它是可取的,它可以写成$line .= $_;
- 建议所需输出的正确描述不是“第二行”而是“以
@
. 请注意,由于正则表达式上没有多行修饰符,因此它将始终仅匹配变量中的第一行段$line
。由于过早连接,它将在每一行上匹配(因为第一行数据以 开头@
),执行第 5-8 行中的代码。
- 将另一行读入
$_
. 它不测试 EOF,但这是无害的。
- 评论行;除了暗示一些混乱之外没有任何意义。
my $line = $line;
是对隐藏外部的新变量的自赋值$line
……主要是,这很奇怪,在较小程度上它是无操作的。你没有使用use strict;
,use warnings;
因为如果你这样做了,你会收到警告。Perl 专家使用use strict;
anduse warnings;
来确保他们没有犯愚蠢的错误;新手应该出于同样的原因使用它们。
- 就其本身而言,好的。但是,条件中的代码并没有真正做太多。它跳过文件中的第二行;它稍后会跳过第四,第六,第八等。
- 好的。
- 好的,但是...如果您只对打印行开始后的行
@
感兴趣,或者只对打印整数 N 的行号 2N+2 感兴趣,那么之前不需要在内存中构建整个字符串打印每一行。打印需要打印的每一行会更简单。