我有一个只包含一行的输入文件:
$ cat input
foo bar
Run Code Online (Sandbox Code Playgroud)
我想在我的脚本中使用这一行,有三种方法可以让我知道:
line=$(cat input)
Run Code Online (Sandbox Code Playgroud)
line=$(<input)
Run Code Online (Sandbox Code Playgroud)
IFS= read -r line < input
Run Code Online (Sandbox Code Playgroud)
例如,使用命令替换意味着我会生成一个子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
Run Code Online (Sandbox Code Playgroud)
tha*_*guy 10
line=$(cat input)是POSIX读取整个文件的方式.它需要一个分叉.
line=$(< input)读取整个文件是一种稍微高效的Bashism.它也有分叉,但不必执行.
没有提到但是mapfile/ readarray显着更高效Bashisms用于逐行读取整个文件到数组中.没有叉子.
IFS= read -r line < input是没有子shell读取单行的POSIX方法.没有叉子.
您只看到后者打开文件的原因很简单,其他人在子shell中执行此操作,并且您没有指定-f跟踪子进程.