为什么不使用&lt; <eof = =“of =”“cat =”“<< eof?=”“

时间:2016-05-15 00:28:33

标签: zsh cat io-redirection

=”“

我'我想知道何时使用cat <<比仅使用<<更可取。我正在测试ZSH shell和

cat <<EOF
Hello world!
EOF

输出相同的

<<EOF
Hello world!
EOF

var=$(cat <<EOF
Hello world!
EOF
)

具有相同的

变量值
var=$(<<EOF
Hello world!
EOF
)

here-doc的两种形式之间有什么实际差异?

2 个答案:

答案 0 :(得分:3)

只要zsh默认行为(例如调用zsh -f),两个示例之间就没有任何差异。我们可以通过zsh -x -f调用两个示例来检查跟踪输出,即使在后一种情况下也会调用cat

尽管Redirections with no command, zshmisc(1)中描述了这些差异。对于没有命令的重定向,zsh会以多种方式运行,所以我们可以做到不破坏任何东西:

  • 明确使用cat
  • 设置localoptions / parameters。
  

没有命令的重定向

     

当一个简单的命令由一个或多个重定向运算符和零个或多个参数赋值组成,但没有命令名时,zsh可以用多种方式运行。

     

如果未设置参数NULLCMD或设置了选项CSH_NULLCMD,则会导致错误。这是csh行为,并且在模拟csh时默认设置为CSH_NULLCMD

     

如果设置了选项SH_NULLCMD,则内置':'将作为具有给定重定向的命令插入。这是模拟sh或ksh时的默认值。

     

否则,如果设置了参数NULLCMD,则其值将用作具有给定重定向的命令。如果同时设置了NULLCMDREADNULLCMD,则当重定向是输入时,将使用后者的值而不是前者的值。 NULLCMD的默认值为“cat”,READNULLCMD的默认值为“more”。因此

     

&LT;文件

     

显示标准输出上的文件内容,如果是终端,则显示分页。 NULLCMDREADNULLCMD可以引用shell函数。

     

- Redirections with no command, zshmisc(1)

因此,在后一种情况下,如果设置了zsh shell选项$var,则不会设置SH_NULLCMD

# I've tested with running `zsh -f` to check the various behaviors.
test-nullcmd () {
  local var=$(<<EOF
Hello world!
EOF
)
  echo "$var"
}

test-nullcmd
#> Hello world!

() {
  setopt localoptions shnullcmd
  test-nullcmd
}
# nothing will be printed

() {
  setopt localoptions cshnullcmd
  test-nullcmd
}
# test-nullcmd:1: redirection with no command (error)

() {
  local NULLCMD=
  test-nullcmd
}
# test-nullcmd:1: redirection with no command (error)

顺便说一句,我们可以仅使用command cat而不是cat来防止别名扩展。

答案 1 :(得分:1)

描述的行为仅限zsh。在zsh上,这是对不必要地调用外部二进制文件(/bin/cat)的显着性能增强。

如果你想将一个heredoc的内容发送到stdout而没有在POSIX shell(例如bash)上启动cat之类的外部工具的开销,那么你需要类似下面这样的内容:

# read heredoc into $var, terminated by first NUL, w/ truthy exit status
IFS= read -r -d '' var <<'EOF' ||:
content goes here
EOF

# emit $var to stdout
printf '%s' "$var"

虽然POSIX不能保证zsh语法比read; printf方法简洁得多,但速度明显快于cat