Труба присваивает переменную

19

Для простоты я хотел бы сделать:

echo cart | assign spo;
echo $spo  

Выход: корзина

Такое assignприложение существует?

Я знаю все способы сделать это с помощью замены.

MageProspero
источник
Почему вы хотите сделать это без замены?
Танатос
Мне нравится обратная польская нотация при написании только трубами. Я гораздо быстрее кодирую и качество / скорость кодов не так важны. Кроме того, я не знаю, когда цепочки проще комментировать части цепочки и выводить текущий вывод, а не удалять тики и т. Д.
MageProspero
Если вас беспокоит простота отладки, подумайте над тем, чтобы поместить команду backticks в ряд отдельных строк. A=$( some | command | here )с каждым из some |, command |и hereна своей линии.
Ройма

Ответы:

11
echo cart | { IFS= read -r spo; printf '%s\n' "$spo"; }

Будет работать (сохранять выходные данные echoбез завершающего символа новой строки в spoпеременной), пока выводится echoтолько одна строка.

Вы всегда можете сделать:

assign() {
  eval "$1=\$(cat; echo .); $1=\${$1%.}"
}
assign spo < <(echo cart)

Следующие решения будут работать в bashсценариях, но не по bashприглашению:

shopt -s lastpipe
echo cat | assign spo

Или:

shopt -s lastpipe
whatever | IFS= read -rd '' spo

Для сохранения вывода whateverдо первых символов NUL ( bashпеременные не могут хранить символы NUL) в $spo.

Или:

shopt -s lastpipe
whatever | readarray -t spo

хранить выходные данные whateverв $spo массиве (одна строка на элемент массива).

Стефан Шазелас
источник
1
не должно быть пробела между IFS=и read?
Цезарсоль
Все приветствуют последнюю трубу. Кроме того, из командной строки необходимо указать примечание + m (ermmm или -m), так как последний канал не работает с активным управлением заданиями.
MageProspero
17

Вы можете сделать что-то вроде этого, если вы используете bash:

echo cart | while read spo; do echo $spo; done

К сожалению, переменная «spo» не будет существовать вне цикла while-do-done. Если вы можете получить то, что хотите, внутри цикла while, это сработает.

Вы можете сделать почти то же самое, что написали выше, в ATT ksh (не в pdksh или mksh) или в невероятном zsh:

% echo cart | read spo
% echo $spo
cart

Таким образом, другое решение будет использовать ksh или zsh.

Брюс Эдигер
источник
1
Вы можете использовать сопроцессы в оболочке Korn (например mksh): echo cart |& while read -p spo; do echo $spo; done( while IFS= read -p -r spo; do…хотя на самом деле лучше использовать )
mirabilos
2

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

spa=$(echo cart)

Назначает cartпеременную $spa.

Зэк-VII
источник
2
Это то, что они называют заменой, которую ОП хотел избежать.
Дмитрий Григорьев
Это было полезно для меня, мне просто нужно было присвоить его переменной, мне было все равно, как оно туда попало!
Крис Марисик
1

Если вы просто хотите вывести текущий конвейерный поток, используйте cat.

echo cart | cat 

Если вы хотите продолжить цепочку команд, попробуйте использовать teeкоманду для вывода результатов.

echo cart | tee /dev/tty | xargs ls

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

alias tout='tee /dev/tty'
echo cart | tout | xargs ls
BillThor
источник
Почему вы хотите передать вывод на равнину cat?
Ройма
1
@roaima Некоторые команды распознают, что они работают на терминале и ведут себя иначе, чем если бы они выводили в канал. В частности, они могут обрезать строки до текущей ширины экрана. Для большинства команд команда cat является избыточной.
BillThor
Ах, хорошо, теперь я вижу, что вы пытались проиллюстрировать. echo | catКонструкт бросил меня.
Ройма
1

Вот мое решение проблемы.

# assign will take last line of stdout and create an environment variable from it
# notes: a.) we avoid functions so that we can write to the current environment
#        b.) aliases don't take arguments, but we write this so that the "argument" appears
#            behind the alias, making it appear as though it is taking one, which in turn
#            becomes an actual argument into the temporary script T2.
# example: echo hello world | assign x && echo %x outputs "hello world"
alias assign="tail -1|tee _T1>/dev/null&&printf \"export \\\$1=\$(cat _T1)\nrm _T*\">_T2&&. _T2"
Брайан Крамер
источник