“ $(cat file)”,“ $(<file)”和=“”“ read =”“ ... =”“ <=”“ file” =“” for =“”文件之间有什么区别? “” with =“” one =“” line?=“”

时间:2018-08-20 19:55:24

标签: bash file strace

=“”

我有一个仅包含一行的输入文件:

$ cat input
foo bar

我想在脚本中使用此行,并且我知道有3种方法来获取它:

line=$(cat input)
line=$(<input)
IFS= read -r line < input

例如,使用命令替换意味着我产生了一个子shell,而对于read我却没有,对吗?还有什么其他区别,有什么方法比其他方法更可取?我还注意到(使用strace),由于某种原因,只有read会触发系统调用openat。其他人怎么可能不这样做?

$ strace ./script |& grep input
read(3, "#!/usr/bin/env bash\n\ncat > input"..., 80) = 80
read(255, "#!/usr/bin/env bash\n\ncat > input"..., 167) = 167
read(255, "\nline=$(cat input)\nline=$(<input"..., 167) = 60
read(255, "line=$(<input)\nIFS= read -r line"..., 167) = 41
read(255, "IFS= read -r line < input\n", 167) = 26
openat(AT_FDCWD, "input", O_RDONLY)     = 3

1 个答案:

答案 0 :(得分:9)

  • line=$(cat input)是读取整个文件的POSIX方法。它需要一个叉子。

  • line=$(< input)是用于读取整个文件的效率稍高的Bashism。它也可以分叉,但不必执行。

  • 没有提及,但是mapfile / readarray是一种高效的Bashism,可以逐行将整个文件读入数组。没有叉子。

  • IFS= read -r line < input是POSIX方式,无需子shell即可读取单行。没有叉子。

之所以只看到后者打开文件,是因为其他人在子shell中进行了操作,而您没有指定-f来跟踪子进程。