Якщо ви хочете лише перший чи два рядки, працює наступний тип хитрощів і уникає проблем буферизації, викликаних використанням двох різних команд для читання вихідного потоку:
$ ps -eF | { IFS= read -r x ; echo "$x" ; grep worker; }
$ ls -la / | { IFS= read -r x ; echo "$x" ; grep sbin; }
read
Вбудований в оболонку і не споживає весь буфер введення тільки для виведення одна лінія, тому використання read
залишає все інше на виході для наступної команди.
Якщо ви хочете підкреслити проблеми буферизації, показані у ваших прикладах, які використовують дві різні команди, додайте sleep
до них, щоб усунути проблеми з тимчасовим терміном і дозволити команді зліва генерувати всі свої результати перед командами праворуч спробувати прочитати будь-яку з це:
$ ps -eF | { sleep 5 ; head -n 1 ; grep worker; }
$ ls -la / | { sleep 5 ; head -n 1 ; grep sbin; }
Тепер обидва вищевказані приклади провалюються однаково - head
зчитується цілий буфер виводу просто для створення одного рядка, і цей буфер недоступний для наступних grep
.
Ви можете побачити проблему буферизації ще чіткіше, використовуючи кілька прикладів, які нумерують вихідні рядки, щоб ви могли сказати, які рядки відсутні:
$ ps -eF | cat -n | { sleep 5 ; head -n 1 ; head ; }
$ ls -la /usr/bin | cat -n | { sleep 5 ; head -n 1 ; head ; }
Простий спосіб побачити проблему буферизації - це використання, seq
що генерує список чисел. Ми можемо легко визначити, які цифри пропущені:
$ seq 1 100000 | { sleep 5 ; head -n 1 ; head ; }
1
1861
1862
1863
1864
1865
1866
1867
1868
1869
Моє рішення про хитрість, що використовує оболонку для читання та повторення першого рядка, працює правильно навіть із доданим затримкою сну:
$ seq 1 100000 | { sleep 5 ; IFS= read -r x ; echo "$x" ; head ; }
1
2
3
4
5
6
7
8
9
10
11
Нижче наводиться повний приклад, що показує head
проблеми буферизації, показує, як
head
витрачається цілий буфер виводу просто для отримання його п'яти рядків кожного разу. Цей спожитий буфер недоступний для наступної
head
команди в послідовності:
$ seq 1 100000 | { sleep 5 ; head -5 ; head -5 ; head -5 ; head -5 ; }
1
2
3
4
5
1861
1862
1863
1864
499
3500
3501
3502
3503
7
5138
5139
5140
5141
Переглядаючи число, 1861
наведене вище, ми можемо обчислити розмір використовуваного буфера head
шляхом підрахунку seq
виходу від 1
до
1860
:
$ seq 1 1860 | wc -c
8193
Ми бачимо, що head
це буферизація, читаючи повний 8 КБ (8 * 1024 байт) вихідної труби за один раз, навіть для отримання лише декількох ліній власного виводу.
head
Іgrep
нічого не робити там.