Rura przypisuje zmienną

19

Dla uproszczenia chciałbym zrobić:

echo cart | assign spo;
echo $spo  

Wyjście: koszyk

Czy taka assignaplikacja istnieje?

Jestem świadomy wszystkich sposobów, aby to zrobić za pomocą substytucji.

MageProspero
źródło
Dlaczego chcesz to zrobić bez zamiany?
Thanatos,
Lubię odwrotny przepływ notacji polskiej, gdy piszę tylko za pomocą potoków. Jestem znacznie szybszym kodowaniem, a jakość / szybkość kodów nie jest tak ważna. Również nie robię, kiedy łańcuchowanie jest łatwiejsze do komentowania części łańcucha i echa bieżącej mocy wyjściowej, zamiast usuwania tików itp.
MageProspero,
Jeśli obawiasz się o łatwość debugowania, rozważ umieszczenie polecenia wstecznego w szeregu oddzielnych linii. A=$( some | command | here )z każdym some |, command |i herena własnej linii.
roaima

Odpowiedzi:

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

Działa (przechowuje wynik echobez końcowego znaku nowej linii w spozmiennej), o ile echowypisuje tylko jedną linię.

Zawsze możesz zrobić:

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

Następujące rozwiązania będą działać w bashskryptach, ale nie w bashmonicie:

shopt -s lastpipe
echo cat | assign spo

Lub:

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

Do przechowywania danych wyjściowych whateverdo pierwszych NUL znaków ( bashzmienne i tak nie mogą przechowywać znaków NUL) $spo.

Lub:

shopt -s lastpipe
whatever | readarray -t spo

do przechowywania danych wyjściowych whateverw $spo tablicy (jeden wiersz na element tablicy).

Stéphane Chazelas
źródło
1
czy nie powinno być odstępu między IFS=i read?
caesarsol,
Cała ostatnia rura. Potrzebny jest również zestaw notatek bocznych + m (ermmm lub -m) z wiersza poleceń, ponieważ zrobi to, ponieważ ostatnia rura nie działa z aktywną kontrolą zadań.
MageProspero
17

Możesz zrobić coś takiego, jeśli użyjesz bash:

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

Niestety zmienna „spo” nie będzie istniała poza pętlą „do zrobienia”. Jeśli możesz uzyskać to, co chcesz zrobić w pętli while, to zadziała.

Możesz właściwie robić dokładnie to, co napisałeś powyżej w ATT ksh (nie w pdksh ani mksh) lub we wspaniałym zsh:

% echo cart | read spo
% echo $spo
cart

Tak więc innym rozwiązaniem byłoby użycie ksh lub zsh.

Bruce Ediger
źródło
1
Możesz użyć koprocesów w skorupie Korna (np. mksh): echo cart |& while read -p spo; do echo $spo; done( while IFS= read -p -r spo; do…Ale lepiej jest użyć )
mirabilos
2

Jeśli dobrze rozumiem problem, chcesz przesłać standardowe wyjście do zmiennej. Przynajmniej tego szukałem i skończyłem tutaj. Więc dla tych, którzy podzielają mój los:

spa=$(echo cart)

Przypisuje cartdo zmiennej $spa.

zack-vii
źródło
2
Tak nazywają substytucję, której PO chciał uniknąć.
Dmitrij Grigoriew
Przydało mi się to, wystarczyło przypisać ją do zmiennej, nie obchodziło mnie, jak się tam dostała!
Chris Marisic
1

Jeśli chcesz tylko wyświetlić bieżący strumień potoku użyj cat.

echo cart | cat 

Jeśli chcesz kontynuować łańcuch poleceń, spróbuj użyć teepolecenia, aby wyświetlić dane wyjściowe.

echo cart | tee /dev/tty | xargs ls

Możesz użyć aliasu, aby skrócić polecenie.

alias tout='tee /dev/tty'
echo cart | tout | xargs ls
BillThor
źródło
Dlaczego chcesz przesyłać dane wyjściowe do zwykłego cat?
roaima
1
@roaima Niektóre polecenia rozpoznają, że działają na terminalu i zachowują się inaczej niż wtedy, gdy są wysyłane do potoku. W szczególności mogą one przycinać linie do bieżącej szerokości ekranu. W przypadku większości poleceń polecenie cat jest zbędne.
BillThor
Ach, ok, widzę teraz to, co próbujesz zilustrować. echo | catKonstrukt wyrzucił mnie.
roaima
1

Oto moje rozwiązanie problemu.

# 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"
Brian Kramer
źródło