К настоящему времени « Бесполезное использование cat
награды» очень хорошо известно, и есть также упоминание о « Бесполезном использовании»echo
(не относится к этому вопросу). Я задаюсь вопросом, должно ли быть «Бесполезное использование echo
в Bash Award»: трубопроводы, кажется, намного медленнее, чем heredocs и Herestrings, согласно некоторым весьма ненаучным измерениям:
Heredocs:
for reps in 1 2 3 do time for i in {1..1000} do cat <<'END' test string END done > /dev/null done real 0m1.786s user 0m0.212s sys 0m0.332s real 0m1.817s user 0m0.232s sys 0m0.332s real 0m1.846s user 0m0.256s sys 0m0.320s
Herestrings
for reps in 1 2 3 do time for i in {1..1000} do cat <<< 'test string' done > /dev/null done real 0m1.932s user 0m0.280s sys 0m0.288s real 0m1.956s user 0m0.248s sys 0m0.348s real 0m1.968s user 0m0.268s sys 0m0.324s
Перенаправление
for reps in 1 2 3 do time for i in {1..1000} do echo 'test string' | cat done > /dev/null done real 0m3.562s user 0m0.416s sys 0m0.548s real 0m3.924s user 0m0.384s sys 0m0.604s real 0m3.343s user 0m0.400s sys 0m0.552s
Как правило, heredocs и herestrings имеют примерно одинаковую скорость (это только один набор данных из нескольких тестов), в то время как перенаправление постоянно более чем на 50% медленнее. Я что-то неправильно понимаю, или это можно использовать как общее правило для команд, читающих стандартный ввод в Bash?
seq
» ;-)cat <<END
противcat <<< "test string"
противecho "test string" | cat
илиcat <<'END'
противcat <<< 'test string'
противecho 'test string' | cat
иметь одинаковое количество разложения в исполнении оболочки на струнах.$(seq $reps)
?Ответы:
Во-первых, давайте сосредоточимся на производительности. Я запускал тесты для немного другой программы на процессоре x86_64, который в основном простаивает и работает под управлением Debian squeeze.
herestring.bash
, используя Herestring для передачи строки ввода:heredoc.bash
используя heredoc для передачи строки ввода:echo.bash
, используяecho
и трубу для прохождения строки ввода:Для сравнения я также рассчитал время работы скриптов под ATT ksh93 и под dash (кроме
herestring.bash
, что у dash нет этих строк).Вот в среднем три раза:
Выводы:
echo
и труба заметно, но не намного быстрее. (Имейте в виду, что это игрушечная программа: в реальной программе большая часть времени обработкиtr
того, что здесь обозначает вызов.)Помимо производительности, есть также ясность и портативность.
<<<
является расширением ksh93 / bash / zsh, которое менее известно, чемecho … |
или<<
. Это не работает в ksh88 / pdksh или в POSIX sh.Единственное место, где
<<<
, возможно, значительно яснее, находится внутри наследственности:против
(Большинство оболочек не справляются с закрытием скобок в конце строки, содержащей
<<EOF
.)источник
<<<
происходит из-rc
за Bourne-подобного мира ракушекzsh
.rc
не добавляю завершающий символ новой строки, но всеbash
,zsh
иksh93
делаю AFAICT.rc
использует трубу там, в то времяbash
,zsh
иksh93
использовать временный файл , как для heredocs.<<<
еще менее полезным.zsh
есть оптимизация=(<<<foo)
для эффективного создания временного файла, который содержит «foo», который не включает в себя разветвление процесса, как это=(echo foo)
было бы.<<<
.Другая причина использовать heredocs (если вам не хватило), что эхо может потерпеть неудачу, если поток не используется. Рассмотрим
pipefail
вариант bash :/bin/true
не использует свой стандартный ввод, ноecho yawn
тем не менее завершает. Однако, если echo попросят напечатать много данных, он не завершится, покаtrue
не завершится:141 - это SIGPIPE (128 + 13) (добавляется 128, потому что bash делает это в соответствии с bash (1):
У Heredocs нет этой проблемы:
источник
pipefail
умолчанию отключено!pipefail
в верхней части каждого сценария. Дай мне все ошибки!Одной из причин, по которой вы можете захотеть использовать echo, является использование некоторого элемента управления символом новой строки, который добавляется в конец heredocs и herestrings:
Три символа
foo
имеет длину 3:Однако трехсимвольная строка здесь состоит из четырех символов:
Трехзначный наследник тоже:
Четвертый символ -
0x0a
символ новой строки .Каким-то образом это волшебным образом согласуется с тем, как bash удаляет эти символы новой строки при получении вывода из суб-оболочки:
Вот команда, которая возвращает четыре символа:
foo
и\n
. '\ N' добавляется echo, он всегда добавляет символ новой строки, если вы не укажете-n
опцию:Однако, присваивая это переменной, завершающий символ новой строки, добавленный echo, удаляется:
Поэтому, если вы смешиваете файлы и переменные и используете их в вычислениях (например, вы не можете использовать heredocs или herestrings, так как они добавят новую строку.
Если вы измените оператор if, чтобы прочитать
тогда тест проходит.
источник