Труба призначає змінну


19

Для простоти я хотів би зробити:

echo cart | assign spo;
echo $spo  

Вихід: візок

Чи існує така assignпрограма?

Мені відомі всі способи зробити це за допомогою заміни.


Чому ти хочеш це робити без заміни?
Танатос

Мені подобається зворотний потік польських нотацій, коли пишуться лише трубами. Я набагато швидше кодую, і якість / швидкість кодів не так важлива. Крім того, я не можу, коли це пов'язано, це привіт простіше коментувати частини ланцюга та
повторювати

Якщо ви стурбовані простотою налагодження, подумайте про те, щоб поставити команду backticks на ряд окремих рядків. A=$( some | command | here )з кожним із some |, command |та hereу своєму власному рядку.
roaima

Відповіді:


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, це спрацює.

Насправді ви можете виконати майже точно те, що ви написали вище, в ATT ksh (не в pdksh або mksh) або в казковому zsh:

% echo cart | read spo
% echo $spo
cart

Отже, іншим рішенням буде використання ksh або zsh.


1
Ви можете використовувати копроцеси в оболонці Корна (наприклад 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?
roaima

1
@roaima Деякі команди визнають, що вони працюють на терміналі і поводяться інакше, ніж якщо вони виводять на трубу. Зокрема, вони можуть усікати лінії до поточної ширини екрана. Для більшості команд команда cat є зайвою.
BillThor

Ну добре, я бачу, що ви намагалися проілюструвати. echo | catКонструкт кинув мене.
roaima

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.