Shell, пишущий сценарий причуд перенаправления ввода

Я знаю, что этому ответили до смерти, но я хотел бы показать фактический пример различий в скорости.

Здесь мы создаем 2 000 000 новых объектов с помощью метода print в Chrome. Мы сохраняем каждый объект в массиве. Помещение print на прототип занимает около 1/2.

18
задан Jon Ericson 8 September 2008 в 22:02
поделиться

8 ответов

read var1 var2 < <(echo "hello world")
8
ответ дан 30 November 2019 в 05:59
поделиться

Сообщению правильно ответили, но я хотел бы предложить альтернативный один лайнер, который, возможно, мог быть несколько полезным.

Для присвоения пространства разделил значения от эха (или stdout в этом отношении) для окружения переменных, Вы могли рассмотреть использование массивов оболочки:

$ var=( $( echo 'hello world' ) )
$ echo ${var[0]}
hello
$ echo ${var[1]}
world

В этом var в качестве примера массив, и к содержанию можно получить доступ с помощью $ конструкции {var [индекс]}, где индекс является индексом массива (запускается с 0).

Тот способ, которым у Вас может быть столько параметров, сколько Вы хотите присвоенный соответствующему индексу массива.

5
ответ дан 30 November 2019 в 05:59
поделиться
#!/bin/sh
echo "hello world" | read var1 var2
echo $var1
echo $var2

не производит вывода, потому что конвейеры выполняют каждый из своих компонентов в подоболочке. Подоболочки наследовали копии из переменных родительской оболочки, вместо того, чтобы совместно использовать их. Попробуйте это:

#!/bin/sh
foo="contents of shell variable foo"
echo $foo
(
    echo $foo
    foo="foo contents modified"
    echo $foo
)
echo $foo

круглые скобки определяют регион кода, который выполняется в подоболочке, и $foo сохраняет свое исходное значение, будучи измененным в них.

Теперь попытка это:

#!/bin/sh
foo="contents of shell variable foo"
echo $foo
{
    echo $foo
    foo="foo contents modified"
    echo $foo
}
echo $foo

фигурные скобки просто для группировки, никакая подоболочка не создается, и $foo, измененный в фигурных скобках, является тем же $foo, измененным вне их.

Теперь попытка это:

#!/bin/sh
echo "hello world" | {
    read var1 var2
    echo $var1
    echo $var2
}
echo $var1
echo $var2

Внутренняя часть фигурные скобки, встроенное чтение создает $var1 и $var2 правильно, и Вы видите, что они отражены. Вне фигурных скобок они больше не существуют. Весь код в фигурных скобках был выполнен в подоболочке , потому что это - один компонент конвейера .

можно поместить произвольные объемы кода между фигурными скобками, таким образом, можно использовать эту piping-into-a-block конструкцию каждый раз, когда необходимо выполнить блок сценария оболочки, который анализирует вывод чего-то еще.

11
ответ дан 30 November 2019 в 05:59
поделиться

Этому уже ответили правильно, но решение еще не было указано. Используйте ksh, не колотите. Сравните:

$ echo 'echo "hello world" | read var1 var2
echo $var1
echo $var2' | bash -s

К:

$ echo 'echo "hello world" | read var1 var2
echo $var1
echo $var2' | ksh -s
hello
world

ksh является превосходящей оболочкой программирования из-за небольших тонкостей как это. (удар является лучшей интерактивной оболочкой, по-моему.)

10
ответ дан 30 November 2019 в 05:59
поделиться

Мое взятие по этой проблеме (использующий Bash):

read var1 var2 <<< "hello world"
echo $var1 $var2
5
ответ дан 30 November 2019 в 05:59
поделиться

Allright, я понял это!

Это - трудная ошибка для ловли, но следует из способа, которым каналы обрабатываются оболочкой. Каждый элемент конвейера работает в отдельном процессе. То, когда наборы команд чтения var1 и var2, устанавливает их он его собственная подоболочка, не родительская оболочка. Таким образом, когда подоболочка выходит, значения var1 и var2 потеряны. Можно, однако, попытаться делать

var1=$(echo "Hello")
echo var1

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

set -- $(echo "Hello World")
var1="$1" var2="$2"
echo $var1
echo $var2

, В то время как я признаю, что это не столь изящно как использование канала, это работает. Конечно, необходимо иметь в виду, что читает, был предназначен для чтения из файлов в переменные, так делая это, чтение от стандартного входа должно быть немного более трудным.

5
ответ дан 30 November 2019 в 05:59
поделиться

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

Выполняют эту команду

$ echo $;cat | read a
10637

и используют pstree-p для рассмотрения рабочих процессов, Вы проводите дополнительное зависание оболочки своей основной оболочки.

    |                       |-bash(10637)-+-bash(10786)
    |                       |             `-cat(10785)
4
ответ дан 30 November 2019 в 05:59
поделиться

Попытка:

echo "hello world" | (read var1 var2 ; echo $var1 ; echo $var2 )

проблема, как несколько человек заявили, состоит в том, что var1 и var2 создаются в подсреде оболочки, которая уничтожается, когда та подоболочка выходит. Вышеупомянутое старается не уничтожать подоболочку, пока результатом не был echo'd. Другое решение:

result=`echo "hello world"`
read var1 var2 <<EOF
$result
EOF
echo $var1
echo $var2
3
ответ дан 30 November 2019 в 05:59
поделиться