Як я міг би передати висновок однієї команди декільком командам?


20

Використовуючи підстановку процесу або групуючи та конфігуруючи, можна передавати вихід ( stdout ) набір команд як вхід для іншої команди.

Приклад:

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

Але чи існує навпаки?

Тобто, чи є спосіб відправити вихід однієї команди як вхід для багатьох інших команд в одному рядку ?

Щось на зразок :

cat testfile | wc | tail -n 5

( Не сприймайте трубопроводи буквально ). Тут я намагаюся передавати вихід cat testfileобом wcіtail -n 5

Іншим прикладом може бути:

( щоб отримати останнє слово речення )

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

Відповіді:


21

Швидка відповідь. Ви можете використовувати, tee >(what_to_do) >(another_thing_to_do)щоб продовжувати виконувати свою команду для тих самих різних речей, які ви хочете зробити.

Приклад:

Вихідний вихідний тестовий файл:

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

Виведення з teeдоданими командами:

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

Кожна команда в трійнику - це лише звичайні команди, які ви використовували б у командному рядку, як і додавання в >(head -1 | wc)роботах.

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

Або ви можете також захопити останнє слово сказати останній рядок, використовуючи awkз $NFз wcа так:

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

ПРИМІТКА: Додавання |команди "pipe" до кінця може змінити за допомогою декількох команд з teeкоманди. У мене є кілька прикладів, які я тестував:

Приклад 1 (команда Pipe, що тягне всі останні слова):

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

Приклад 2 (Не показує вихід команд wc. Командна труба, що захоплює 3-е слово.):

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

Приклад 3 (Захоплення 3-го слова рядка ехо. Команда 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

Приклад 4 (Захоплення останнього слова рядка ехо. Команда 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

Сподіваюся, це допомагає!


3
Я люблю чай і каву! '-)
Старійшина Гік

1
Заява про впорядкованість продукції між різними споживачами teeнеправдивою. Причина, коли ви зазвичай отримуєте правильне замовлення, полягає в тому, що на машині з низьким навантаженням перший споживчий процес запускається першим. На більш зайнятій машині перший споживач може спати, перш ніж він щось надрукує.
Матей Девід

@MateiDavid Я не можу довести це інакше, тому я просто видалив заяву. Немає великого.
Терранс

2
Дивіться мою відповідь. Але якщо серйозніше, то teeпоняття не має про споживачів - вони створюються тим, bashхто обробляє лінію. Все, що bashпотрібно зробити - це скопіювати дескриптори відкритого файлу. Крім того, у вас є кілька споживачів, які пишуть у дескриптори файлів, відкриті в одному файлі. Ядро про це піклується, але, безумовно, порядок, який вони з'явилися в bashкомандному рядку, не буде фактором.
Матей Девід

17

Вам потрібно teeрозділити потік на частини. Спробуйте:

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

Примітки:

  • Якщо кілька процесів ( wc, tail) всі записують у stdout:

    • Можливо, ви отримаєте прихований вихід.

    • Немає гарантій щодо порядку, в якому відображатиметься їх результат. Щоб побачити це, спробуйте sleep 1; wc -wяк другий споживач.

  • teeзаблокується, якщо будь-яке його призначення не споживає потік досить швидко. Це означає, що пункти призначення подаватимуться приблизно з однаковою швидкістю (за модулем буферування фіксованого розміру). Виправити це непросто, єдина альтернатива - зберегти потік у файл та подати споживачам окремо. Для wcі tailце не є проблемою.

Останнє слово простіше зробити:

echo "some random words" | awk '{print $NF}'

5

У moreutilsпакеті передбачена команда pee(злиття труби і трійника, що ви думали?), Яка робить саме це.

Для першого прикладу ви використовуєте:

cat testfile | pee wc "tail -n 5"

Другий приклад складніший, тому що ви хочете передати два входи до останньої команди. Я, мабуть, використовував би awkяк інші відповіді.

Посилання: https://joeyh.name/code/moreutils/

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.