Чтение значений в переменную оболочки из канала - PullRequest
180 голосов
/ 30 апреля 2010

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

echo "hello world" | test=($(< /dev/stdin)); echo test=$test
test=

echo "hello world" | read test; echo test=$test
test=

echo "hello world" | test=`cat`; echo test=$test
test=

где я хочу, чтобы вывод был test=hello world. Я пытался поместить "" кавычки вокруг "$test", что тоже не работает.

Ответы [ 15 ]

3 голосов
/ 30 апреля 2010

Вставка чего-либо в выражение, содержащее присваивание, ведет себя не так.

Вместо этого попробуйте:

test=$(echo "hello world"); echo test=$test
2 голосов
/ 09 июля 2015

следующий код:

echo "hello world" | ( test=($(< /dev/stdin)); echo test=$test )

тоже будет работать, но откроет еще одну новую под-оболочку после канала, где

echo "hello world" | { test=($(< /dev/stdin)); echo test=$test; }

не будет.


Мне пришлось отключить управление заданиями, чтобы использовать метод chepnars '(я запускал эту команду из терминала):

set +m;shopt -s lastpipe
echo "hello world" | read test; echo test=$test
echo "hello world" | test="$(</dev/stdin)"; echo test=$test

Руководство Bash говорит: :

lastpipe

Если установлено, и управление заданиями не активно , оболочка запускает последнюю команду конвейера не выполняется в фоновом режиме в текущей оболочке окружающая среда.

Примечание: управление заданиями по умолчанию отключено в неинтерактивной оболочке, и поэтому вам не нужно set +m внутри скрипта.

1 голос
/ 10 июля 2012

Я думаю, что вы пытались написать сценарий оболочки, который мог бы принимать ввод от stdin. но пока вы пытаетесь сделать это встроенным образом, вы заблудились, пытаясь создать эту переменную test =. Я думаю, что не имеет смысла делать это встроенным, и поэтому он не работает так, как вы ожидаете.

Я пытался уменьшить

$( ... | head -n $X | tail -n 1 )

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

cat program_file.c | line 34

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

22:14 ~ $ cat ~/bin/line 
#!/bin/sh

if [ $# -ne 1 ]; then echo enter a line number to display; exit; fi
cat | head -n $1 | tail -n 1
22:16 ~ $ 

вот, пожалуйста.

0 голосов
/ 05 мая 2019

Интеллектуальный скрипт, который может считывать данные из PIPE и аргументы командной строки:

#!/bin/bash
if [[ -p /proc/self/fd/0 ]]
    then
    PIPE=$(cat -)
    echo "PIPE=$PIPE"
fi
echo "ARGS=$@"

Выход:

$ bash test arg1 arg2
ARGS=arg1 arg2

$ echo pipe_data1 | bash test arg1 arg2
PIPE=pipe_data1
ARGS=arg1 arg2

Объяснение: Когда скрипт получает любые данные по каналу, stdin / proc / self / fd / 0 будет символической ссылкой на канал.

/proc/self/fd/0 -> pipe:[155938]

Если нет, он будет указывать на текущий терминал:

/proc/self/fd/0 -> /dev/pts/5

Опция bash if -p может проверить, что это труба или нет.

cat - читает из stdin.

Если мы используем cat -, когда нет stdin, он будет ждать вечно, поэтому мы помещаем его в условие if.

0 голосов
/ 21 августа 2015

Как насчет этого:

echo "hello world" | echo test=$(cat)
...