2016-05-15 161 views
2

我想知道什么时候使用cat <<比简单地使用<<更可取。我在一家ZSH壳测试和为什么不使用<< EOF代替cat << EOF?

cat <<EOF 
Hello world! 
EOF 

输出相同的

<<EOF 
Hello world! 
EOF 

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

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

什么是两种形式在这里,文档之间的实际差别相同的变量值?

+0

你可能会标记这个'zsh'而不是'shell',因为它只适用于那个单一的shell。 –

+0

是的,它会更好。我不知道这是一个zsh非常具体的扩展。 –

回答

2

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

虽然这些差异在Redirections with no command, zshmisc(1)中描述。 zsh的行为将在不使用任何命令重定向几种方法,所以我们可以做些什么不会打破任何东西:

  • 要使用cat明确。
  • 设置localoptions /参数。

重定向没有命令

当一个简单的命令由一个或多个重定向操作符和零所或多个参数分配的,但没有得到命令名,zsh中可以表现在几个方面。

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

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

否则,如果设置了参数NULLCMD,则其值将用作具有给定重定向的命令。如果同时设置了NULLCMDREADNULLCMD,则当重定向是输入时,将使用后者的值而不是前者的值。为NULLCMD缺省值是“猫”和用于READNULLCMD是“more'.Thus

<文件

示出了在标准输出文件的内容,与寻呼如果这是一个终端。 NULLCMDREADNULLCMD可能涉及shell函数。

- Redirections with no command, zshmisc(1)

因此,在后一种情况下,$var不会,如果zsh的​​外壳选项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,以防止别名扩展。

+0

真棒回答。记录,测试并提供关于猫的不平衡的良好建议。非常感谢你! –

1

描述的行为是zsh-only。在zsh上,与不必要地调用外部二进制(/bin/cat)相比,这是一项显着的性能增强。

如果你想发出一个定界符的内容到标准输出,而不在POSIX外壳如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" 

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

相关问题