З sed
вами ви можете:
sed '24q;1,5d;12,18d' <infile >outfile
... Можливо, було б більш ефективним рішенням head
. Дон уже продемонстрував, як це може працювати дуже добре, але я теж пограв із цим. Щось, що ви можете зробити для вирішення цього конкретного випадку:
for n in 5 6 7 6
do head -n"$n" >&"$((1+n%2))"
done <infile >outfile 2>/dev/null
... що закликає head
4 рази записувати або до, outfile
або /dev/null
залежно від того, чи є цією ітерацією значення $n
парного чи непарного числа.
Для більш загальних випадків я співав це разом із деякими іншими речами:
somehead()(
### call it like:
### somehead -[repeat] [-][numlines]* <infile >outfile
set -e -- "${1#-}" "$@" #-e for arg validation
r=; cd -- "${TMP:-/tmp}" #go to tmp
dd bs=4096 of="$$$$" <&4 2>&3 & #dd <in >tmpfile &bg
until [ -s "$$$$" ]; do :; done #wait while tmpfile empty
exec <"$$$$" 4<&-; rm "$$$$" #<tmpfile; rm tmpfile
[ "$3${1}0" -ne "$3${2#?}0" ] || #validate args - chk $1
shift "$(((r=-${1:--1})||1))"; shift #shift 1||2
while [ "$(((r+=(_n=1))-1))" -ne 0 ] && #while ! $rptmax &&
IFS= read -r l && # ! EOF &&
printf "%.$(($1>0?${#l}+1:0))s" "$l # ? printf do
"; do for n do [ "${n#-}" -gt 0 ] || exit #args all -[nums>0]
head "-n$((${n#-}-_n))" >&"$((n>(_n=0)?1:3))" #head -n?$1 >?[+-]
done; done #done and done
) 4<&0 3>/dev/null #4<for dd 3>for head
Це можна зробити так, як:
seq 100 | somehead -1 -5 6 -7 6
... які друкує ...
6
7
8
9
10
11
19
20
21
22
23
24
Першим аргументом очікується, що це повторне підрахунок з префіксом a -
, або, якщо цього не відбувається, просто a -
. Якщо підрахунок передбачений, він повторить шаблон лінії, вказаний у наступних аргументах, стільки разів, скільки зазначено, і зупиниться, як тільки це зробить.
Для кожного аргументу, що випливає, він буде інтерпретувати негативне ціле число, щоб вказати кількість рядків, до якого слід записати, /dev/null
а додатне ціле число, щоб вказати кількість рядків, до яких слід записати stdout
.
Отже, у наведеному вище прикладі вона друкує перші 5 рядків до /dev/null
, наступні 6 до stdout
, наступні 7 /dev/null
знову і наступні 6 ще раз до stdout
. Діставшись до останнього свого аргументу і повністю проїхавшись через -1
повторний підрахунок, він потім виходить. Якби це був перший аргумент, -2
він би повторив процес ще раз, або -
як би довше, ніж міг.
Для кожного циклу аргументу цикл while
обробляється один раз. У верхній частині кожної петлі перший рядок stdin
зчитується в змінну оболонки $l
. Це необхідно, тому що while head </dev/null; do :; done
буде повторюватися нескінченно - head
вказує при поверненні, коли він досяг кінця файлу. Таким чином, перевірка на EOF присвячена read
і printf
запише $l
плюс новий рядок stdout
лише у тому випадку, якщо другий аргумент є натуральним числом.
read
Перевірка ускладнює петлю трохи , тому що відразу ж після того, як інший цикл називається - for
цикл , який перебирає арг , 2-$#
як представлено в $n
кожній ітерації батьківського while
циклу. Це означає, що для кожної ітерації перший аргумент повинен бути зменшений на одиницю від значення, вказаного в командному рядку, але всі інші повинні зберігати свої початкові значення, і тому значення $_n
var маркера віднімається від кожного, але тільки коли-небудь має a значення більше 0 для першого аргументу
Це становить основний цикл функції, але основна частина коду знаходиться вгорі і призначена для того, щоб функція могла чисто буферувати навіть трубу як вхід. Це працює, спочатку викликаючи фонове зображення, dd
щоб скопіювати його в tmpfile на виході з розмірами 4 к. Штуки. Потім функція встановлює цикл утримування - який майже ніколи не повинен завершити навіть єдиний повний цикл - лише для того, щоб переконатися, що dd
він зробив принаймні одне записування у файл до того, як функція потім замінить свій stdin дескриптором файлів, пов'язаним з tmpfile і після цього відразу від’єднується файл ізrm
. Це дає можливість функції надійно обробляти потік, не вимагаючи пасток або інакше для очищення - як тільки функція звільнить її претензію на fd, tmpfile перестане існувати, оскільки єдине посилання з файловою системою вже видалено.
head
іtail
? Якщо так, то ваше рішення майже найкраще, що ви можете зробити. Якщо вам дозволено використовувати інші програми,sed
абоawk
ви можете дозволити кращі рішення (наприклад, з меншою кількістю викликів процесу).