2016-05-15 3 views
2

Мне интересно, если использовать cat << предпочтительнее, используя <<. Я проверяю в оболочке ЗШ иПочему бы не использовать << EOF вместо кошки << EOF?

cat <<EOF 
Hello world! 
EOF 

выдает то же самое из

<<EOF 
Hello world! 
EOF 

.

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

имеет ту же переменную величину

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

Каковы практические различия между этими двумя формами здесь-документ?

+0

Вы можете пометить этот 'zsh' вместо' shell', поскольку он применим только к этой единственной оболочке. –

+0

Да, это лучше. Я не знал, что это очень специфическое расширение zsh. –

ответ

2

До тех пор, пока поведение по умолчанию zsh (например, вызывает zsh -f), между двумя примерами не существует дефференцирования. Мы могли бы проверить вывод трассировки при вызове двух примеров с zsh -x -f, cat будет называться фактически даже в последнем случае.

Хотя эти отличия описаны в Redirections with no command, zshmisc(1). ЗШ будет вести себя по-разному для перенаправлений без какой-либо команды, так что мы можем сделать это, чтобы ничего не сломать:

  • Чтобы использовать cat явно.
  • Чтобы установить локальные параметры/параметры.

Перенаправление с командой не

Когда простая команда состоит из одного или нескольких операторов перенаправления и ноль или более назначений параметров, но без имени команды, ЗШ может вести себя по-разному.

Если параметр NULLCMD не установлен или установлен параметр CSH_NULLCMD, возникает ошибка. Это поведение csh, и CSH_NULLCMD устанавливается по умолчанию при эмуляции csh.

Если установлен параметр SH_NULLCMD, встроенная функция:: устанавливается в качестве команды с данными перенаправлениями. Это значение по умолчанию при эмуляции sh или ksh.

В противном случае, если установлен параметр NULLCMD, его значение будет использоваться как команда с данными перенаправлениями. Если установлены оба значения NULLCMD и READNULLCMD, тогда значение последнего будет использоваться вместо первого, когда перенаправление является входом.По умолчанию для NULLCMD является «кошка» и READNULLCMD является «more'.Thus

< файл

показывает содержимое файла на стандартный вывод, с подкачкой, если это терминал. NULLCMD и READNULLCMD могут ссылаться на функции оболочки.

- Redirections with no command, zshmisc(1)

Таким образом, в последнем случае, $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) 

BTW, мы могли бы использовать command cat скорее чем cat исключительно для предотвращения расширения псевдонимов.

+0

Удивительный ответ. Документированные, проверенные и с хорошим советом о неучастиях кошки. Большое спасибо! –

1

Описанное поведение - только zsh. В zsh это значительное повышение производительности за излишнее обращение к внешнему двоичному файлу (/bin/cat).

Если вы хотите, чтобы испустить содержимое А Heredoc на стандартный вывод без накладных расходов на запуск внешнего инструмента, как cat на POSIX оболочки, такие как Баш, вам нужно что-то вроде следующего вместо:

# 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.