Przekazywanie dwóch argumentów do polecenia za pomocą potoków

22

Zwykle musimy przekazać tylko jeden argument:

echo abc | cat
echo abc | cat some_file -
echo abc | cat - some_file

Czy istnieje sposób na przekazanie dwóch argumentów? Coś jak

{echo abc , echo xyz} | cat
cat `echo abc` `echo xyz`

Mógłbym najpierw zapisać oba wyniki w pliku

echo abc > file1
echo xyz > file2
cat file1 file2

Ale wtedy mogę przypadkowo zastąpić plik, co nie jest w porządku. Przechodzi w nieinteraktywny skrypt. Zasadniczo potrzebuję sposobu na przekazanie wyników dwóch dowolnych poleceń catbez zapisywania do pliku.


AKTUALIZACJA: Przykro nam, przykład maskuje problem. Chociaż { echo abc ; echo xyz ; } | catwydaje się, że działa, wynik jest spowodowany przez echos, a nie przez cat.

Lepszym przykładem byłby ten, { cut -f2 -d, file1; cut -f1 -d, file2; } | paste -d,który nie działa zgodnie z oczekiwaniami.

Z

file1:
a,b
c,d

file2:
1,2
3,4

Oczekiwany wynik to:

b,1
d,3

ZDECYDOWANY:

Użyj podstawienia procesu :cat <(command1) <(command2)

Możesz też utworzyć nazwane potoki, używając mkfifo:

mkfifo temp1
mkfifo temp2
command1 > temp1 &
command2 > temp2 &
cat temp1 temp2

Mniej elegancki i bardziej szczegółowy, ale działa dobrze, o ile upewnisz się, że temp1 i temp2 nie istnieją wcześniej.

goweon
źródło
1
To sprawia, że ​​drapię się po głowie. Chcesz połączyć dwa różne polecenia z jednym kotem?
user606723,
2
Wiesz, że „potokowanie” i „argumenty” to dwa zupełnie niepowiązane pojęcia, prawda?
Ignacio Vazquez-Abrams
@Ignacio err ... Nie znam się na Linuksie, więc tak naprawdę nie znam różnicy. Zawsze myślałem, że pipowanie oznacza, że ​​bierze poprzedni wynik jako argument. Chcesz oświecić mnie?
goweon
@ firebat nie, potok oznacza przyjęcie standardowego wejścia poprzedniego polecenia jako standardowego wejścia następnego polecenia. Nadal możesz mieć argumenty, które są inną koncepcją.
Rich Homolka
Ponadto, o ile tekst aktualizacji zawiera dane wyjściowe cat, po prostu chcesz, aby instrukcje wydawały się oddzielne od cat, czego nie można zrobić, ponieważ są one serializowane w jednym strumieniu.
Rich Homolka

Odpowiedzi:

17

Myślę, że chcesz „Proces zastępowania” http://tldp.org/LDP/abs/html/process-sub.html . Działa również na zsh, choć ma więcej opcji, a składnia może być inna.

Tworzy pseudo plik ( /dev/fd/something) dla każdego podstawienia. To całkiem przydatne. Polecenie może być odczytywane tylko jako strumień, co oznacza, że ​​nie może przesuwać się tam iz powrotem z fseek. Musi to odczytać jako strumień bajtów, jak potok.

Twoje przykłady działają jako podstawienie procesu:

cat <(echo abc) <(echo xyz)
paste -d, <(cut -f2 -d, file1) <(cut -f1 -d, file2)

Pomyśl o tym jak o narzędziu do wykorzystania procesu i udawaj, że jest plikiem bez plików tymczasowych.

(z mojej wcześniejszej odpowiedzi )

Rich Homolka
źródło
2

Nawiasy klamrowe faktycznie działały, ponieważ operator potoku połączy standardowe wyjścia zgrupowanych poleceń ze standardowym wejściem trzeciego.

Możesz stwierdzić, że wydruk nie pochodzi z echa, uruchamiając dowolne polecenie, które nie korzysta ze standardowego wejścia, np. { echo 1; echo 2;} | echo 3Wypisze 3 zamiast 1 \ n2 \ n3.

Jednak nie jest to rzecz, której chciałeś, ponieważ dwa polecenia w nawiasach klamrowych zapisują do tego samego wyniku, który przypomina catwyniki. Aby wygenerować dwa różne wyniki do użycia jako dwa argumenty dla poleceń takich jak paste, musisz użyć pliku tymczasowego lub nazwanego potoku.

Możesz użyć mktempdo wygenerowania unikalnego pliku tymczasowego lub mkfifodo utworzenia pliku potoku FIFO.

billc.cn
źródło
Wielkie dzięki za odpowiedź, szukałem tego rozwiązania przez wiele dni i w końcu znalazłem odpowiedź tutaj.
Saeed Falsafin
2

Lubię xargs Jako przykład chcę znaleźć rozmiar wszystkich danych mysql w katalogu / usr / local

osx: użytkownik lokalny $ pwd
/ usr / local
osx: użytkownik lokalny $ ls | grep mysql
mysql
mysql-5.0.51a-osx10.5-x86_64
mysql-5.0.51b-osx10.5-x86_64
mysql-5.1.39-osx10.5-x86_64
mysql-5.6.17-osx10,7-x86_64
os x: użytkownik lokalny $ ls | grep mysql | sudo xargs du -sh
4,0 tys. Mysql
2,8G mysql-5.0.51a-osx10.5-x86_64
 10G mysql-5.0.51b-osx10.5-x86_64
 25G mysql-5.1.39-osx10.5-x86_64
753M mysql-5.6.17-osx10,7-x86_64
osx: użytkownik lokalny $ 

xargs

zimnica
źródło