2016-05-15 202 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

相關問題