为啥 Perl 的两个 arg open 似乎去掉了换行符?

Posted

技术标签:

【中文标题】为啥 Perl 的两个 arg open 似乎去掉了换行符?【英文标题】:Why does Perl's two arg open seem to strip newlines?为什么 Perl 的两个 arg open 似乎去掉了换行符? 【发布时间】:2012-06-28 21:52:00 【问题描述】:

当我使用包含尾随换行符的文件名调用 perl 的两个参数 open() 时,将忽略换行符。但是,三参数版本保留了换行符。

为什么行为不同?为什么换行符表面上被剥离了?

-- 文件“nl”不存在。实现它

$ ls -1 nl;触摸 nl; ls -1 nl
ls: nl: 没有这样的文件或目录
nl

-- 尝试三参数打开 "nl\n" → ENOENT

strace 显示了我期望的行为,FWIW。

$ perl -E 'open(F, "&1 | grep nl
open("nl\n", O_RDONLY|O_LARGEFILE) = -1 ENOENT (没有那个文件或目录)

-- 现在,试试双参数 open "nl\n" → 成功?

$ perl -E 'open(F, "nl\n") or die $!'

-- 什么?为什么这行得通?我们来看看 strace。

哦,它忽略了换行符:

$ strace -e trace=open perl -E 'open(F, "nl\n") or die $!' 2>&1 | grep nl
open("nl", O_RDONLY|O_LARGEFILE) = 3

-- "nl" 仍然是唯一的文件

$ ls
nl

背景:

$ perl -v

这是为 i686-linux-thread-multi 构建的 perl 5,版本 16,subversion 0 (v5.16.0)。

【问题讨论】:

【参考方案1】:

perldoc perlopentut:

另一个需要注意的重要事情是,就像在 shell 中一样,文件名之前或之后的任何空格都会被忽略。这很好,因为您不希望它们做不同的事情:

open INFO, "<datafile"
open INFO, "< datafile"
open INFO, "< datafile"

这不是错误,而是一项功能。因为open 以使用重定向箭头来指定如何打开文件的方式模仿shell,所以它也会在文件名本身周围的额外空格方面这样做。要访问具有顽皮名称的文件,请参阅Dispelling the Dweomer。

还有一个 3 参数版本的 open,它可以让您将特殊的重定向字符放入它们自己的参数中:

在这种情况下,要打开的文件名是 $datafile 中的实际字符串,因此您不必担心 $datafile 包含可能影响打开模式的字符,或者文件名开头的空格将被吸收在 2 参数版本中。此外,减少不必要的字符串插值是一件好事。

【讨论】:

这是 3-arg open 的优势之一。 这是 3-arg open 的缺点之一 ;-)【参考方案2】:

这很简单:因为 2-arg open 的语法类似于 shell 的语法,甚至可以使用管道。

【讨论】:

也许如果opensysopen 分别被称为shell_openC_open,人们可能会更快地掌握他们的本性。好吧,20年前的人们;没有人知道那些恐龙语言了。 @tchrist,哦,我真希望system 被这样拆分(shell($shell_cmd) -vs- system($prog, @opt_args)

以上是关于为啥 Perl 的两个 arg open 似乎去掉了换行符?的主要内容,如果未能解决你的问题,请参考以下文章

从 perl 主脚本中分离 .exe

perl打开读取文件(open)

为啥 IPC::Open2::open2 返回父进程 ID?

优化 Perl 脚本以关联两个文件之间的记录

为啥 Perl v5.22 找不到所有的句子边界?

为啥 IPC::Open3 调用 cmd.exe 而不是请求的程序?