Jak przekazałbym dane wyjściowe jednego polecenia do wielu poleceń?

20

Stosując podstawienie procesu lub grupując i potokując, można przekazać wyjściu (standardowe wyjście ) zestaw poleceń jako dane wejściowe dla innego polecenia.

Przykład:

wc < <(echo hi;echo bye)
(echo hi; bye) | wc

Ale czy jest na odwrót?

Czy istnieje sposób, aby wysłać dane wyjściowe jednego polecenia jako dane wejściowe dla wielu innych poleceń w jednym wierszu ?

Coś jak :

cat testfile | wc | tail -n 5

( Nie bierz rurociągów dosłownie ). Tutaj próbuję przekazać dane wyjściowe cat testfiledo obu wcitail -n 5

Innym przykładem może być:

( aby uzyskać ostatnie słowo zdania )

echo "some random words"| wc -c | cut -f(out put of wc -c) (output of first echo)
Severus Tux
źródło

Odpowiedzi:

21

Szybka odpowiedź. Możesz użyć tee >(what_to_do) >(another_thing_to_do)polecenia, aby wykonać tyle różnych czynności, ile chcesz.

Przykład:

Oryginalny plik wyjściowy pliku testowego:

:~$ cat testfile.txt 
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616

Dane wyjściowe z teedodanymi poleceniami:

:~$ cat testfile.txt | tee >(tail -1) >(wc) >(awk '{print $3,$1,$2}')
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616
LITEONIT Device Model:
TW0XFJWX550854187616 Serial Number:
      2      10      91
Serial Number:    TW0XFJWX550854187616

Każde polecenie w tee jest zwykłymi poleceniami, których używałbyś w wierszu poleceń, podobnie jak dodawanie >(head -1 | wc)działa.

:~$ cat testfile.txt | tee >(tail -1) >(head -1 | wc)  >(awk '{print $3,$1,$2}')
Device Model:     LITEONIT LCS-256M6S 2.5 7mm 256GB
Serial Number:    TW0XFJWX550854187616
      1       7      52
LITEONIT Device Model:
TW0XFJWX550854187616 Serial Number:
Serial Number:    TW0XFJWX550854187616

Albo można też złapać ostatnie słowo powiedzieć ostatnią linię korzystając awkze $NFz wctak dobrze jak to:

:~$ cat testfile.txt | tail -1 | tee >(wc) >(awk '{print $NF}')
Serial Number:    TW0XFJWX550854187616
TW0XFJWX550854187616
      1       3      39

UWAGA: Dodanie |polecenia potoku do końca może zastąpić wiele poleceń z teepolecenia. Mam tutaj kilka przykładów, które testowałem:

Przykład 1 (polecenie potoku ciągnące wszystkie ostatnie słowa):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) | awk '{print $NF}'
words
24
5
1

Przykład 2 (Nie pokazuje wyniku poleceń wc. Polecenie potoku przechwytuje 3 słowo.):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) | awk '{print $3}'
just

Przykład 3 (Chwytanie trzeciego słowa linii echa. Polecenie tee.):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) >(awk '{print $3}')
This is just five words
just
24
5
1

Przykład 4 (Chwytanie ostatniego słowa linii echa. Polecenie Tee.):

:~$ echo "This is just five words" | tee >(wc -l) >(wc -w) >(wc -c) >(awk '{print $NF}')
This is just five words
words
24
5
1

Mam nadzieję że to pomoże!

Terrance
źródło
3
Uwielbiam herbatę i kawę! '-)
Elder Geek
1
Stwierdzenie dotyczące uporządkowania produkcji między różnymi konsumentami teejest fałszywe. Powodem, dla którego zazwyczaj otrzymujesz prawidłowe zamówienie, jest to, że na maszynie o niskim obciążeniu pierwszy proces konsumencki jest uruchamiany jako pierwszy. Na bardziej obciążonej maszynie pierwszego konsumenta można uśpić, zanim cokolwiek wydrukuje.
Matei David,
@MateiDavid Nie mogę tego udowodnić inaczej, więc właśnie usunąłem oświadczenie. Żadnego biggie.
Terrance
2
Zobacz moją odpowiedź. Ale co ważniejsze, teenie ma pojęcia o konsumentach - są one tworzone przez tego, bashkto przetwarza linię. Wystarczy bashskopiować otwarte deskryptory plików. Poza tym kilku klientów pisze do deskryptorów plików otwartych na tym samym pliku. Jądro się tym zajmuje, ale z pewnością kolejność, w jakiej pojawiły się w bashlinii poleceń, nie będzie miała znaczenia.
Matei David
17

Musisz teepodzielić strumień na części. Próbować:

cat testfile | tee >(wc -l) >(wc -w) >(wc -c) | tail -n 5

Uwagi:

  • Jeśli wszystkie procesy ( wc, tail) zapisują na standardowe wyjście:

    • Może pojawić się zniekształcony obraz wyjściowy.

    • Nie ma gwarancji co do kolejności, w jakiej pojawi się ich wynik. Aby to zobaczyć, spróbuj sleep 1; wc -wjako drugi konsument.

  • teezablokuje się, jeśli którykolwiek z jego miejsc docelowych nie zużyje wystarczająco szybko strumienia. Oznacza to, że odbiorcy będą zasilani danymi wejściowymi z mniej więcej podobną prędkością (modulo buforowanie o stałej wielkości). Nie ma na to łatwej poprawki, jedyną alternatywą jest zapisanie strumienia do pliku i osobne przekazanie go konsumentom. Dla wci tailto nie jest problem.

W przypadku ostatniego słowa łatwiej jest zrobić:

echo "some random words" | awk '{print $NF}'
Matei David
źródło
5

moreutilsPakiet zawiera polecenia pee(seryjnej rury i tee, co ty na to?), Który robi dokładnie to.

Jako pierwszy przykład użyjesz:

cat testfile | pee wc "tail -n 5"

Drugi przykład jest bardziej skomplikowany, ponieważ chcesz przekazać dwa dane wejściowe do ostatniego polecenia. Prawdopodobnie użyłbym awkjako innych odpowiedzi.

Link: https://joeyh.name/code/moreutils/

T. Verron
źródło