$(<file)
(也适用于`<file`
)是由zsh
和复制的Korn shell的特殊运算符bash
。它看起来确实很像命令替换,但实际上并非如此。
在POSIX shell中,一个简单的命令是:
< file var1=value1 > file2 cmd 2> file3 args 3> file4
所有部分都是可选的,您只能进行重定向,仅进行命令,仅进行分配或组合。
如果存在重定向但没有命令,则会执行重定向(因此a > file
将打开并截断file
),但是什么也没有发生。所以
< file
打开file
以供阅读,但是由于没有命令,因此什么也没有发生。因此,file
将其关闭,仅此而已。如果$(< file)
是简单的命令替换,则它将扩展为空。
在POSIX规范中$(script)
,如果script
仅包含重定向,则会产生未指定的结果。这是为了让Korn shell具有特殊的行为。
在ksh(此处已通过进行测试ksh93u+
)中,如果脚本仅包含一个且仅包含重定向(无命令,无赋值)的简单命令(尽管前后允许使用注释),并且第一个重定向为stdin(fd 0)仅输入(<
,<<
或<<<
)重定向,因此:
$(< file)
$(0< file)
$(<&3)
($(0>&3)
实际上也是因为实际上是同一运算符)
$(< file > foo 2> $(whatever))
但不是:
$(> foo < file)
- 也不
$(0<> file)
- 也不
$(< file; sleep 1)
- 也不
$(< file; < file2)
然后
- 除了第一个重定向之外的所有内容都将被忽略(将它们解析掉)
- 并扩展为文件/ heredoc / herestring的内容(如果使用诸如之类的东西,也可以从文件描述符中读取任何内容
<&3
)减去结尾的换行符。
像使用$(cat < file)
不同之处在于
- 读取是通过外壳而不是内部完成的
cat
- 没有管道也没有额外的过程
- 由于上述原因,由于内部代码未在子shell中运行,因此此后仍保留任何修改(如
$(<${file=foo.txt})
或$(<file$((++n)))
)
- 读错误(尽管在打开文件或复制文件描述符时不会出错)将被静默忽略。
在zsh
,它的不同之处在于,当只有一个文件输入重定向特殊行为时,才会触发相同(<file
或0< file
没有<&3
,<<<here
,< a < b
...)
但是,除了模拟其他shell以外,在:
< file
<&3
<<< here...
也就是说,只有输入重定向而不执行命令时,在命令替换之外zsh
运行$READNULLCMD
(默认为寻呼机),并且当同时存在输入和输出重定向时,$NULLCMD
(cat
默认为),即使$(<&3)
没有被识别为特殊运算符,它仍然可以像ksh
通过调用分页器执行操作一样工作(该分页器的行为类似,cat
因为其标准输出将是管道)。
但是同时ksh
的$(< a < b)
将扩大到的内容a
,在zsh
,它扩展到的内容a
和b
(或只是b
如果multios
选项被禁用),$(< a > b)
将复制a
到b
并扩大到什么,等等。
bash
具有相似的运算符,但有一些区别:
允许在注释之前但之后不允许注释:
echo "$(
# getting the content of file
< file)"
可以,但是:
echo "$(< file
# getting the content of file
)"
扩展为空。
像in中一样zsh
,只有一个文件stdin重定向,尽管没有回退到a $READNULLCMD
,所以$(<&3)
,$(< a < b)
请执行重定向,但扩展到无。
- 由于某些原因,尽管
bash
不调用cat
,它仍然派生出一个通过管道来馈送文件内容的进程,这使其优化程度远低于其他Shell。它像一个作用$(cat < file)
在那里cat
将是一个内置cat
。
- 由于上述原因,之后所做的任何更改都将丢失(
$(<${file=foo.txt})
例如,在上述的中,此$file
分配随后将丢失)。
在中bash
,IFS= read -rd '' var < file
(也可以在中使用zsh
)是一种将文本文件的内容读入变量的更有效的方法。它还具有保留尾随换行符的好处。另请参阅$mapfile[file]
中的内容zsh
(在zsh/mapfile
模块中,仅适用于常规文件),该内容也适用于二进制文件。
请注意,ksh
与ksh93相比,基于pdksh的变体有一些变体。有趣的是,mksh
(这些pdksh衍生的外壳之一)
var=$(<<'EOF'
That's multi-line
test with *all* sorts of "special"
characters
EOF
)
通过在不使用临时文件或管道的情况下扩展here文档的内容(不带结尾字符)的方式优化了here文档的内容,这与here document的情况不同,这使其成为有效的多行引用语法。
可以移植到所有版本ksh
,zsh
并且bash
,最好是限制只能$(<file)
避免意见,并铭记修改变量内可能会或可能不会被保留做。
bash
将解释为cat filename
”时,是否表示此行为特定于命令替换?因为如果我自己运行< filename
,bash不会解决问题。它不会输出任何内容,并让我返回提示。