6

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

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

-- 文件“nl”不存在。做了

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

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

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

$ perl -E 'open(F, "<", "nl\n") 或死 $!'
-e 第 1 行没有这样的文件或目录。

$ strace -e trace=open perl -E 'open(F, "<", "nl\n") 或死 $!' 2>&1 | grep nl
open("nl\n", O_RDONLY|O_LARGEFILE) = -1 ENOENT(没有这样的文件或目录)

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

$ perl -E 'open(F, "nl\n") 或死 $!'

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

哦,它忽略了换行符:

$ strace -e trace=open perl -E 'open(F, "nl\n") 或死 $!' 2>&1 | grep nl
打开(“nl”,O_RDONLY|O_LARGEFILE)= 3

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

$ ls
荷兰语

背景:

$ perl -v

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

4

2 回答 2

11

perldoc perlopentut

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

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

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

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

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

于 2012-06-28T21:59:57.873 回答
2

这很简单:因为 2-argopen的语法近似于 shell 的语法,甚至到了允许管道的程度。

于 2012-06-28T22:05:19.300 回答