от
Может кто-нибудь объяснить такое поведение? Работа:
#!/bin/sh
echo "hello world" | read var1 var2
echo $var1
echo $var2
результаты в ничего не выход, а:
#!/bin/sh
echo "hello world"

Ваш ответ

Отображаемое имя (по желанию):
Конфиденциальность: Ваш электронный адрес будет использоваться только для отправки уведомлений.

10 Ответы

0 голосов
от
Может кто-нибудь объяснить такое поведение? Работа:
#!/bin/sh
echo "hello world" | read var1 var2
echo $var1
echo $var2
результаты в ничего не выход, а:
#!/bin/sh
echo "hello world"
0 голосов
от
Недавнее дополнение к
bash
вариант
lastpipe
, что позволяет последней команды в конвейере работать в текущей оболочке, а не подуровень, когда контроль работы отключается.
#!/bin/bash
set  m      # Deactiveate job control
shopt 

действительно выход

hello
world
0 голосов
от
#!/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 правильно и вы видите, что они вам вторит. Вне скобок, они не существуют больше. Весь код в фигурные скобки была запущена в подоболочку, потому что это один из компонентов трубопровода. Вы можете поставить произвольное количество кода в фигурных скобках, так что вы можете использовать эти трубы-В-а-блочного строительства, когда вам нужно, чтобы запустить блок shell-скрипт, который парсит вывод о чем-то другом.
0 голосов
от
Это уже правильно ответили, но решение еще не было указано. Использование КШ, а не Баш. Сравните:
$ echo 'echo "hello world" | read var1 var2
echo $var1
echo $var2' | bash 

К:

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

КШ-это превосходный оболочки программирования из-за такой мелочи. (Баш лучше интерактивную оболочку, на мой взгляд.)
0 голосов
от
read var1 var2
0 голосов
от
Пост уже правильно ответили, но я хотел бы предложить альтернативу один лайнер, который мог бы пригодиться. Для присвоения разделенных пробелами значений от эхо (или stdout на то пошло) в переменных оболочки, вы могли бы рассмотреть использование массивов оболочки:
$ var=( $( echo 'hello world' ) )
$ echo ${var[0]}
hello
$ echo ${var[1]}
world
В этом примере var массив и содержание могут быть доступны с помощью конструкции ${ВАР[индекс]}, где индекс массива индекс (начинается с 0). Таким образом, вы можете иметь столько параметров, сколько вы хотите присваивается соответствующий индекс массива.
0 голосов
от
Мое мнение по данной проблеме (с использованием bash):
read var1 var2
0 голосов
от
Ладно, я все понял! Это жесткий баг поймать, но результаты от трубы обрабатываются оболочки. Каждый элемент трубопровода выполняется в отдельном процессе. Когда команда чтения устанавливает var1 и var2, устанавливает им свою собственную оболочку, а не оболочку. Поэтому, когда подуровень выходов, значения var1 и var2 будут потеряны. Можно, однако, попробовать делать
var1=$(echo "Hello")
echo var1
которая возвращает ожидаемый ответ. К сожалению, это работает только для отдельных переменных, вы не можете установить сразу несколько. Для того, чтобы за один раз вы должны прочитать в одной переменной и нарезать его на несколько переменных или использовать что-то вроде этого несколько переменных:
set 

Хотя я признаю, что это не так элегантно, как через трубу, это работает. Конечно, вы должны иметь в виду, что чтение было предназначено для чтения из файла в переменные, что позволяет читать стандартный входной поток должен быть немного сложнее.
0 голосов
от
Это потому, что версия канала создает подоболочку, которая считывает переменную в своем локальном пространстве, который затем разрушается, когда в том случае, когда выходит. Выполнить эту команду
$ echo $$;cat | read a
10637
и использовать pstree -P, чтобы посмотреть на запущенные процессы, вы увидите дополнительную оболочку висит от вашей основной оболочки.
    |                       |
0 голосов
от
Попробуйте:
echo "hello world" | (read var1 var2 ; echo $var1 ; echo $var2 )
Проблема, как несколько человек заявили, что var1 и var2 создаются в среде подуровень, что разрушается, когда что-подуровне выходы. Вышеизложенное позволяет избежать разрушения подуровень, пока результат был бы эхо. Другим решением является:
result=`echo "hello world"`
read var1 var2
...