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


19

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

echo cart | assign spo;
echo $spo  

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

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

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


Почему вы хотите сделать это без замены?
— Танатос

Мне нравится обратная польская нотация при написании только трубами. Я гораздо быстрее кодирую и качество / скорость кодов не так важны. Кроме того, я не знаю, когда цепочки проще комментировать части цепочки и выводить текущий вывод, а не удалять тики и т. Д.
— 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.


2
Это то, что они называют заменой, которую ОП хотел избежать.
— Дмитрий Григорьев

Это было полезно для меня, мне просто нужно было присвоить его переменной, мне было все равно, как оно туда попало!
— Крис Марисик

1

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

echo cart | cat 

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

echo cart | tee /dev/tty | xargs ls

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

alias tout='tee /dev/tty'
echo cart | tout | xargs ls

Почему вы хотите передать вывод на равнину 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"
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.