Dengan sed
Anda mungkin melakukannya:
sed '24q;1,5d;12,18d' <infile >outfile
... Mungkin solusi yang lebih efisien dapat diperoleh head
. Don sudah mendemonstrasikan bagaimana itu bisa bekerja dengan sangat baik, tetapi saya juga bermain-main dengannya. Sesuatu yang mungkin Anda lakukan untuk menangani kasus khusus ini:
for n in 5 6 7 6
do head -n"$n" >&"$((1+n%2))"
done <infile >outfile 2>/dev/null
... yang akan memanggil head
4 kali penulisan untuk outfile
atau /dev/null
tergantung pada apakah nilai iterasi untuk $n
angka genap atau ganjil.
Untuk kasus-kasus yang lebih umum, saya menggabungkan ini dari beberapa hal lain yang sudah saya miliki:
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
Ini dapat melakukan hal Anda seperti:
seq 100 | somehead -1 -5 6 -7 6
... yang mencetak ...
6
7
8
9
10
11
19
20
21
22
23
24
Ia mengharapkan arg pertama menjadi hitungan berulang yang diawali dengan -
, atau, gagal itu, hanya a -
. Jika hitungan diberikan, ia akan mengulangi pola garis yang diberikan dalam argumen berikut sebanyak yang ditentukan dan berhenti segera setelah itu dilakukan.
Untuk setiap argumen yang mengikutinya akan menafsirkan bilangan bulat negatif untuk menunjukkan jumlah baris yang harus ditulis /dev/null
dan bilangan bulat positif untuk menunjukkan jumlah baris yang harus ditulis stdout
.
Jadi pada contoh di atas ia mencetak 5 baris pertama /dev/null
, 6 berikutnya stdout
, 7 berikutnya /dev/null
lagi dan 6 berikutnya sekali lagi stdout
. Setelah mencapai argumen terakhir dan sepenuhnya berputar melalui -1
hitungan ulang, ia kemudian berhenti. Jika arg pertama adalah -2
itu akan mengulangi proses sekali lagi, atau jika -
selama itu bisa.
Untuk setiap siklus arg, while
loop diproses sekali melalui. Di bagian atas setiap loop, baris pertama dari stdin
dibaca ke variabel shell $l
. Hal ini diperlukan karena while head </dev/null; do :; done
akan mengulangi tanpa batas - head
tidak menunjukkan pengembalian ketika telah mencapai akhir file. Jadi pemeriksaan terhadap EOF didedikasikan untuk read
dan printf
akan menulis $l
plus baris baru stdout
hanya jika argumen kedua adalah bilangan bulat positif.
The read
cek mempersulit loop kecil karena segera setelah loop lain disebut - sebuah for
lingkaran yang iterates atas args 2-$#
yang diwakili di $n
setiap iterasi dari induknya while
lingkaran. Ini berarti bahwa untuk setiap iterasi, arg pertama harus dikurangi dengan satu dari nilai yang ditentukan pada baris perintah, tetapi semua yang lain harus mempertahankan nilai aslinya, sehingga nilai $_n
marker var dikurangkan dari masing-masing, tetapi hanya pernah memegang nilai lebih besar dari 0 untuk arg pertama.
Itu merupakan loop utama dari fungsi, tetapi sebagian besar kode berada di bagian atas dan dimaksudkan untuk memungkinkan fungsi untuk buffer bahkan pipa sebagai input. Ini bekerja dengan terlebih dahulu memanggil latar belakang dd
untuk menyalinnya ke tmpfile pada output di bloksi 4k sepotong. Fungsi ini kemudian mengatur loop terus - yang seharusnya hampir tidak pernah menyelesaikan bahkan satu siklus penuh - hanya untuk memastikan bahwa dd
telah membuat setidaknya satu tulis ke file sebelum fungsi kemudian mengganti stdin dengan deskriptor file yang terhubung ke tmpfile dan setelah itu segera putuskan tautan file denganrm
. Hal ini memungkinkan fungsi untuk memproses aliran secara andal tanpa memerlukan jebakan atau sebaliknya untuk pembersihan - segera setelah fungsi melepaskannya mengklaim pada fd tmpfile akan tidak ada lagi karena satu-satunya tautan filesystem yang dinamai telah dihapus.
head
dantail
? Jika demikian, solusi Anda adalah yang terbaik yang dapat Anda lakukan. Jika Anda diizinkan menggunakan program lain,sed
atauawk
mungkin mengizinkan solusi yang lebih bagus (mis. Dengan lebih sedikit pemanggilan proses).