Với sed
bạn có thể làm:
sed '24q;1,5d;12,18d' <infile >outfile
... Có thể có một giải pháp hiệu quả hơn có thể có head
. Don đã chứng minh làm thế nào nó có thể hoạt động rất tốt, nhưng tôi cũng đã chơi xung quanh nó. Một cái gì đó bạn có thể làm để xử lý trường hợp cụ thể này:
for n in 5 6 7 6
do head -n"$n" >&"$((1+n%2))"
done <infile >outfile 2>/dev/null
... sẽ gọi head
4 lần viết hoặc đến outfile
hoặc /dev/null
tùy thuộc vào giá trị lặp đó cho $n
số chẵn hay số lẻ.
Đối với các trường hợp tổng quát hơn, tôi đã kết hợp điều này với nhau từ một số nội dung khác mà tôi đã có:
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
Điều này có thể làm việc của bạn như:
seq 100 | somehead -1 -5 6 -7 6
... mà in ...
6
7
8
9
10
11
19
20
21
22
23
24
Nó hy vọng đối số đầu tiên của nó là số đếm lặp lại có tiền tố là a -
, hoặc, không thành công, chỉ là a -
. Nếu một số đếm được cung cấp, nó sẽ lặp lại mô hình dòng được đưa ra trong các đối số sau đây nhiều lần như đã chỉ định và dừng lại ngay khi nó đã làm như vậy.
Đối với mỗi đối số theo sau nó sẽ diễn giải một số nguyên âm để chỉ ra một số đếm dòng nên được ghi vào /dev/null
và một số nguyên dương để chỉ ra một số lượng dòng nên được ghi vào stdout
.
Vì vậy, trong ví dụ trên, nó in 5 dòng đầu tiên, 6 dòng /dev/null
tiếp theo stdout
, 7 /dev/null
dòng tiếp theo và 6 dòng tiếp theo một lần nữa stdout
. Đã đạt đến điểm cuối cùng của nó và hoàn toàn đạp xe qua -1
số lần lặp lại, sau đó nó bỏ cuộc. Nếu đối số đầu tiên là -2
nó sẽ lặp lại quá trình một lần nữa, hoặc nếu -
nó có thể.
Đối với mỗi chu kỳ arg, while
vòng lặp được xử lý một lần thông qua. Ở đầu mỗi vòng lặp, dòng đầu tiên từ stdin
được đọc vào biến shell $l
. Điều này là cần thiết bởi vì while head </dev/null; do :; done
nó sẽ lặp lại vô thời hạn - head
không cho biết sự trở lại của nó khi nó đã đến cuối tập tin. Vì vậy, kiểm tra đối với EOF được dành riêng read
và printf
sẽ ghi $l
cộng với một dòng mới stdout
chỉ khi đối số thứ hai là số nguyên dương.
Việc read
kiểm tra làm phức tạp vòng lặp một chút bởi vì ngay sau khi một vòng lặp khác được gọi - một for
vòng lặp lặp lại các đối số 2-$#
như được biểu thị $n
cho mỗi lần lặp của while
vòng lặp cha của nó . Điều này có nghĩa là với mỗi lần lặp, đối số đầu tiên phải được giảm bởi một từ giá trị được chỉ định trên dòng lệnh, nhưng tất cả các giá trị khác nên giữ lại các giá trị ban đầu của chúng, và do đó, giá trị của $_n
var đánh dấu được trừ đi từ mỗi, nhưng chỉ giữ một giá trị lớn hơn 0 cho đối số đầu tiên.
Điều đó tạo thành vòng lặp chính của chức năng, nhưng phần lớn mã nằm ở trên cùng và nhằm mục đích cho phép chức năng đệm sạch ngay cả một đường ống làm đầu vào. Điều này hoạt động bằng cách trước tiên gọi một nền tảng dd
để sao chép nó vào một tmpfile trên đầu ra với kích thước 4k một mảnh. Sau đó, hàm sẽ thiết lập một vòng giữ - gần như không bao giờ hoàn thành ngay cả một chu kỳ đầy đủ - chỉ để đảm bảo rằng dd
đã thực hiện ít nhất một lần ghi vào tệp trước khi hàm thay thế stdin của nó bằng một mô tả tệp được liên kết với tmpfile và sau đó ngay lập tức hủy liên kết tệp vớirm
. Điều này cho phép chức năng xử lý luồng một cách đáng tin cậy mà không yêu cầu bẫy hoặc nếu không để dọn dẹp - ngay khi chức năng giải phóng nó yêu cầu trên fd, tmpfile sẽ ngừng tồn tại vì liên kết hệ thống tệp có tên duy nhất của nó đã bị xóa.
head
vàtail
? Nếu vậy, giải pháp của bạn là khá nhiều tốt nhất bạn có thể làm. Nếu bạn được phép sử dụng các chương trình khác,sed
hoặcawk
có thể cho phép các giải pháp đẹp hơn (nghĩa là có ít yêu cầu xử lý hơn).