Bagaimana saya meneruskan output dari satu perintah ke banyak perintah?

20

Menggunakan substitusi proses atau dengan mengelompokkan & perpipaan, seseorang dapat melewatkan output ( stdout ) seperangkat perintah sebagai input untuk perintah lain.

Contoh:

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

Tetapi adakah yang sebaliknya?

Yaitu, Apakah ada cara untuk mengirim output dari satu perintah sebagai input untuk banyak perintah lain dalam satu baris ?

Sesuatu seperti :

cat testfile | wc | tail -n 5

( Jangan mengambil pipa secara harfiah ). Di sini saya mencoba untuk melewatkan keluaran cat testfileuntuk keduanya wcdantail -n 5

Contoh lain adalah:

( untuk mendapatkan kata terakhir dari sebuah kalimat )

echo "some random words"| wc -c | cut -f(out put of wc -c) (output of first echo)
Severus Tux
sumber

Jawaban:

21

Jawaban cepat. Anda dapat menggunakan tee >(what_to_do) >(another_thing_to_do)untuk terus menjalankan perintah Anda untuk banyak hal berbeda yang ingin Anda lakukan.

Contoh:

Output file uji asli:

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

Output dengan teeperintah ditambahkan:

:~$ 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

Setiap perintah dalam tee hanyalah perintah biasa yang akan Anda gunakan pada baris perintah, seperti tambah dalam >(head -1 | wc)karya juga.

:~$ 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

Atau Anda juga dapat mengambil kata terakhir dari mengucapkan baris terakhir dengan menggunakan awkdengan $NFdengan wcjuga seperti ini:

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

CATATAN: Menambahkan |perintah pipa ke ujung dapat mengesampingkan menggunakan beberapa perintah dari teeperintah. Saya punya beberapa contoh di sini yang telah saya uji:

Contoh 1 (Perintah pipa menarik semua kata terakhir):

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

Contoh 2 (Tidak menunjukkan output dari perintah wc. Perintah pipa meraih kata ke-3.):

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

Contoh 3 (Mengambil kata ke-3 dari baris gema. Perintah 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

Contoh 4 (Meraih kata terakhir dari baris gema. Perintah 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

Semoga ini membantu!

Terrance
sumber
3
Saya suka tee dan kopi! '-)
Penatua Geek
1
Pernyataan tentang pemesanan output antara berbagai konsumen teeadalah salah. Alasan Anda biasanya mendapatkan pesanan yang benar adalah bahwa pada mesin beban rendah, proses konsumen pertama harus dijalankan terlebih dahulu. Pada mesin yang lebih sibuk, konsumen pertama mungkin ditidurkan sebelum mencetak apa pun.
Matei David
@MateiDavid Saya tidak bisa membuktikannya, jadi saya baru saja menghapus pernyataan itu. Bukan masalah besar.
Terrance
2
Lihat jawaban saya. Tapi yang lebih serius, teetidak tahu tentang konsumen - mereka diciptakan oleh bashsiapa yang memproses garis. Yang bashdilakukan hanyalah menyalin deskriptor file yang terbuka. Di luar itu, Anda memiliki beberapa konsumen yang menulis ke deskriptor dibuka pada file yang sama. Kernel menangani hal itu, tetapi tentu saja urutan mereka muncul pada bashbaris perintah tidak akan menjadi faktor.
Matei David
17

Anda perlu teemembagi aliran menjadi beberapa bagian. Mencoba:

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

Catatan:

  • Jika beberapa proses ( wc, tail) semuanya menulis ke stdout:

    • Anda mungkin mendapatkan output kacau.

    • Tidak ada jaminan tentang urutan di mana output mereka akan muncul. Untuk melihat ini, cobalah sleep 1; wc -wsebagai konsumen kedua.

  • teeakan memblokir jika salah satu tujuannya tidak mengkonsumsi aliran dengan cukup cepat. Artinya, tujuan akan diberi masukan dengan kecepatan yang hampir sama (modulo buffering ukuran tetap). Tidak ada perbaikan yang mudah untuk ini, satu-satunya alternatif adalah menyimpan aliran ke file, dan memberi makan kepada konsumen secara terpisah. Karena wcdan tailini bukan masalah.

Untuk kata terakhir, lebih mudah dilakukan:

echo "some random words" | awk '{print $NF}'
Matei David
sumber
5

The moreutilspaket menyediakan perintah pee(merge pipa dan tee, apa yang Anda pikirkan?) Yang tidak tepat.

Untuk contoh pertama Anda, Anda akan menggunakan:

cat testfile | pee wc "tail -n 5"

Contoh kedua lebih rumit karena Anda ingin melewatkan dua input ke perintah terakhir. Saya mungkin akan menggunakan awkjawaban yang lain.

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

T. Verron
sumber