Perl 的钻石操作符(空文件句柄)当前正在读取哪个文件?

18
我正在使用Perl的diamond<>操作符从命令行指定的文件中读取。
我想报告消息,例如"在文件$FILENAME的第$.行出现问题",但是如何确定当前由diamond使用的文件?

只是一个提示:使用$ARGV来检测打开的文件是危险的,例如:mycmd file.1 file.1 file.1(具有相同名称的多个文件)。最好使用eof - Guidobot
“外部包”所带来的问题是令人沮丧和荒谬的。大多数Perl模块只是具有.pm扩展名的源文件,不需要安装过程。默认情况下,@INC将当前目录包括在内,因此只需将必要的文件复制到与源文件相同的目录中即可使包可用并满足依赖关系。 - Borodin
@Borodin 如果语言本身就有某个功能,我更愿意知道它。就这么简单。 - PypeBros
如果可以不下载和安装Perl模块就能达到相同的效果,那么推荐需要下载和安装Perl模块的解决方案是不合适的。你表达的偏好非常像一个共同的咒语,即解决方案不能涉及安装模块,这掩盖了从Stack Overflow解决方案复制任何内容也是“外部”的事实。你还应该记住,有许多核心模块是默认与Perl一起安装的,要求排除这些模块的解决方案是不公平的。 - Borodin
1个回答

19

参见perlvar

    $ARGV

Contains the name of the current file when reading from <> .

同时也要考虑在 perlvar 中的 $.。如果你使用 perl -n 命令,可能不会按照你想要的方式执行,因为在 perl -n 的使用情况下计数器没有被重置

$.

Current line number for the last filehandle accessed.

Each filehandle in Perl counts the number of lines that have been read from it. (Depending on the value of $/ , Perl's idea of what constitutes a line may not match yours.) When a line is read from a filehandle (via readline() or <> ), or when tell() or seek() is called on it, $. becomes an alias to the line counter for that filehandle.

You can adjust the counter by assigning to $. , but this will not actually move the seek pointer. Localizing $. will not localize the filehandle's line count. Instead, it will localize perl's notion of which filehandle $. is currently aliased to.

$. is reset when the filehandle is closed, but not when an open filehandle is reopened without an intervening close(). For more details, see I/O Operators in perlop. Because <> never does an explicit close, line numbers increase across ARGV files (but see examples in eof).

You can also use HANDLE->input_line_number(EXPR) to access the line counter for a given filehandle without having to worry about which handle you last accessed.

Mnemonic: many programs use "." to mean the current line number.

以下是一个例子:

$ perl -nE 'say "$., $ARGV";' foo.pl bar.pl
1, foo.pl
2, foo.pl
3, foo.pl
4, foo.pl
5, foo.pl
6, foo.pl
7, foo.pl
8, foo.pl
9, foo.pl
10, foo.pl
11, foo.pl
12, foo.pl
13, bar.pl
14, bar.pl
15, bar.pl

如果您想要重置,需要在读取循环的结尾检查 eof(感谢 @Borodin)。还可以参考 Perldoc 关于 eof
$ perl -nE 'say "$., $ARGV"; close ARGV if eof' foo.pl bar.pl

是的,我已经知道了$。谢谢$ARGV:不知何故,它逃过了我的注意。 - PypeBros
@sylvainulg 看看这个例子,它让我很困惑。如果句柄只是重新打开到另一个文件,它就不会被重置。 - simbabque
4
标准的方法是在读取循环的末尾写入close ARGV if eof。这将重置$.为零。 - Borodin
@simbabque:在 perldoc -f eof 中有很好的记录。 - Borodin
1
您IP地址为143.198.54.68,由于运营成本限制,当前对于免费用户的使用频率限制为每个IP每72小时10次对话,如需解除限制,请点击左下角设置图标按钮(手机用户先点击左上角菜单按钮)。 - Wolf
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接