Z sedtobą możesz zrobić:
sed '24q;1,5d;12,18d' <infile >outfile
... Być może można by uzyskać bardziej wydajne rozwiązanie head. Don już pokazał, jak to może działać bardzo dobrze, ale bawiłem się również tym. Coś, co możesz zrobić, aby rozwiązać ten konkretny przypadek:
for n in 5 6 7 6
do head -n"$n" >&"$((1+n%2))"
done <infile >outfile 2>/dev/null
... który wywołałby head4 razy pisząc na outfilelub w /dev/nullzależności od tego, czy wartość tej iteracji $njest liczbą parzystą czy nieparzystą.
W bardziej ogólnych przypadkach, zebrałem to razem z kilku innych rzeczy, które już miałem:
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
Może to zrobić coś takiego:
seq 100 | somehead -1 -5 6 -7 6
... które drukuje ...
6
7
8
9
10
11
19
20
21
22
23
24
Oczekuje, że jego pierwszy argument będzie liczbą powtórzeń poprzedzoną znakiem -, lub, w przypadku braku takiej liczby , tylko -. Jeśli podano liczbę, powtórzy wzór linii podany w poniższych argumentach tyle razy, ile określono, i zatrzyma się, gdy tylko to zrobi.
Dla każdego następującego argumentu zinterpretuje ujemną liczbę całkowitą wskazującą liczbę wierszy, w której należy zapisać, /dev/nulloraz dodatnią liczbę całkowitą wskazującą liczbę wierszy, w której należy zapisać stdout.
Tak więc w powyższym przykładzie wypisuje pierwsze 5 wierszy do /dev/null, następne 6 do stdout, następne 7 do /dev/nullponownie i kolejne 6 ponownie do stdout. Po osiągnięciu ostatniego z argumentów i pełnym przejściu -1liczby powtórzeń, następnie kończy pracę. Gdyby był pierwszy argument, -2powtórzyłby ten proces jeszcze raz lub -tak długo, jak to możliwe.
Dla każdego cyklu argowania whilepętla jest przetwarzana raz. Na górze każdej pętli pierwszy wiersz z stdinjest wczytywany do zmiennej powłoki $l. Jest to konieczne, ponieważ while head </dev/null; do :; donebędzie się powtarzało w nieskończoność - headwskazuje w swoim zwrocie, kiedy osiągnie koniec pliku. Zatem kontrola EOF jest dedykowana readi printfzapisze $lplus nowy wiersz stdouttylko wtedy, gdy drugi argument jest dodatnią liczbą całkowitą.
readCheck komplikuje pętli trochę, bo zaraz po drugiej pętli nazywa - forpętla która iteruje argumenty 2-$#reprezentowane w $ndla każdej iteracji jego macierzystej whilepętli. Oznacza to, że dla każdej iteracji pierwszy argument musi być pomniejszony o jeden z wartości określonej w wierszu poleceń, ale wszystkie pozostałe powinny zachować swoje oryginalne wartości, więc wartość zmiennej $_nvar jest odejmowana od każdej, ale zawsze zawiera wartość wartość większa niż 0 dla pierwszego argumentu.
To stanowi główną pętlę funkcji, ale większość kodu znajduje się na górze i ma na celu umożliwić tej funkcji czyste buforowanie nawet potoku jako danych wejściowych. Działa to najpierw poprzez wywołanie tła w ddcelu skopiowania go do pliku tmp na wyjściu przy rozmiarach bloków 4k na kawałek. Następnie funkcja ustanawia pętlę wstrzymania - która prawie nigdy nie powinna ukończyć nawet jednego pełnego cyklu - tylko po to, aby upewnić się, że dddokonała przynajmniej jednego zapisu do pliku, zanim funkcja zastąpi swoje standardowe wejście deskryptorem pliku powiązanym z plikiem tmp i potem natychmiast rozłącza plik za pomocąrm. Dzięki temu funkcja niezawodnie przetwarza strumień, nie wymagając pułapek ani w inny sposób do oczyszczenia - jak tylko funkcja zwolni swoje roszczenie na fd, plik tmp przestanie istnieć, ponieważ jego jedyne nazwane łącze do systemu plików zostało już usunięte.
headitail? Jeśli tak, Twoje rozwiązanie jest prawie najlepsze, co możesz zrobić. Jeśli możesz korzystać z innych programówsedlub możeszawkpozwolić na lepsze rozwiązania (tj. Z mniejszą liczbą wywołań procesów).