К суммировать параметры для , используя read
в конце [концептуального эквивалента] конвейера в POSIX-подобных оболочках:
Подводя итог: в bash по умолчанию и всегда в строго POSIX-совместимых оболочках все команды в конвейере выполняются в subshell , поэтому переменных они создают или изменяют не будет виден для текущей оболочки (не будет существовать после завершения конвейера).
Следующие охватывают bash
, ksh
, zsh
и sh
([в основном] оболочки только для POSIX-функций, такие как dash
) и показывают пути избежать создания подоболочки, чтобы сохранить переменные, созданные / измененные read
.
Если минимальный номер версии не указан, предположим, что даже «довольно старые» версии поддерживают его (рассматриваемые функции существуют уже давно, но я не знаю конкретно, когда они были представлены.
Обратите внимание, что в качестве [POSIX-совместимой] альтернативы решениям ниже вы всегда можете записать вывод команды в [временный] файл, а затем передать его в read
как < file
, что также позволяет избежать подоболочки.
ksh
и zsh
: Обходной путь / изменение конфигурации вообще не требуется:
Встроенная read
по умолчанию запускается в оболочке current при использовании в качестве команды last в конвейере.
По-видимому, ksh
и zsh
по умолчанию run любая команда на этапе last конвейера в оболочке current .
Наблюдается в ksh 93u+
и zsh 5.0.5
.
Если вы точно знаете, в какой версии была представлена эта функция, дайте мне знать.
#!/usr/bin/env ksh
#!/usr/bin/env zsh
out= # initialize output variable
# Pipe multiple lines to the `while` loop and collect the values in the output variable.
printf '%s\n' one two three |
while read -r var; do
out+="$var/"
done
echo "$out" # -> 'one/two/three/'
bash 4.2+
: используйте опцию lastpipe
shell
В bash версии 4.2 или выше, при включении опции оболочки lastpipe
последний сегмент конвейера запускается в current shell, что позволяет читать для создания переменных, видимых текущей оболочке.
#!/usr/bin/env bash
shopt -s lastpipe # bash 4.2+: make the last pipeline command run in *current* shell
out=
printf '%s\n' one two three |
while read -r var; do
out+="$var/"
done
echo "$out" # -> 'one/two/three/'
bash
, ksh
, zsh
: использовать процесс замены
Грубо говоря, подстановка процесса - это способ сделать вывод команды похожим на временный файл.
out=
while read -r var; do
out+="$var/"
done < <(printf '%s\n' one two three) # <(...) is the process substitution
echo "$out" # -> 'one/two/three'
bash
, ksh
, zsh
: используйте здесь-строку с подстановкой команды
out=
while read -r var; do
out+="$var/"
done <<< "$(printf '%s\n' one two three)" # <<< is the here-string operator
echo "$out" # -> 'one/two/three'
Обратите внимание на необходимость двойных кавычек подстановки команд для защиты ее вывода от расширений оболочки .
#!/bin/sh
out=
while read -r var; do
out="$out$var/"
done <<EOF # <<EOF ... EOF is the here-doc
$(printf '%s\n' one two three)
EOF
echo "$out" # -> 'one/two/three'
Обратите внимание, что по умолчанию вам нужно поместить конечный разделитель - EOF
, в данном случае - в самом начале строки, и что после него не должно быть символов.