Z sed
tobą 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 head
4 razy pisząc na outfile
lub w /dev/null
zależności od tego, czy wartość tej iteracji $n
jest 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/null
oraz 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/null
ponownie i kolejne 6 ponownie do stdout
. Po osiągnięciu ostatniego z argumentów i pełnym przejściu -1
liczby powtórzeń, następnie kończy pracę. Gdyby był pierwszy argument, -2
powtórzyłby ten proces jeszcze raz lub -
tak długo, jak to możliwe.
Dla każdego cyklu argowania while
pętla jest przetwarzana raz. Na górze każdej pętli pierwszy wiersz z stdin
jest wczytywany do zmiennej powłoki $l
. Jest to konieczne, ponieważ while head </dev/null; do :; done
będzie się powtarzało w nieskończoność - head
wskazuje w swoim zwrocie, kiedy osiągnie koniec pliku. Zatem kontrola EOF jest dedykowana read
i printf
zapisze $l
plus nowy wiersz stdout
tylko wtedy, gdy drugi argument jest dodatnią liczbą całkowitą.
read
Check komplikuje pętli trochę, bo zaraz po drugiej pętli nazywa - for
pętla która iteruje argumenty 2-$#
reprezentowane w $n
dla każdej iteracji jego macierzystej while
pę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 $_n
var 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 dd
celu 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 dd
dokonał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.
head
itail
? Jeśli tak, Twoje rozwiązanie jest prawie najlepsze, co możesz zrobić. Jeśli możesz korzystać z innych programówsed
lub możeszawk
pozwolić na lepsze rozwiązania (tj. Z mniejszą liczbą wywołań procesów).