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
最初の引数は、接頭辞がである-
か、失敗した場合は単にであると想定してい-
ます。カウントが提供された場合、指定された回数だけ後続の引数で指定されたラインパターンを繰り返し、実行が完了するとすぐに停止します。
続く各引数について、書き込まれる必要がある行数を示すには負の整数を、書き込まれる必要が/dev/null
ある行数を示すには正の整数を解釈しstdout
ます。
したがって、上記の例では、最初の5行を/dev/null
に、次の6行をstdout
に、次の7 行をに、次の6 行をに出力/dev/null
しstdout
ます。引数の最後に到達し、-1
繰り返しカウントを完全に循環した後、終了します。最初の引数があった場合は-2
、プロセスをもう一度繰り返したか、または-
できる限り長く繰り返していたでしょう。
argサイクルごとに、while
ループが1回処理されます。各ループの先頭で、最初の行stdin
がシェル変数に読み込まれます$l
。はwhile head </dev/null; do :; done
無期限に繰り返されるため、これは必要head
です。ファイルの終わりに達したときに、その戻りを示します。したがって、EOFに対するチェックは専用でread
あり、2番目の引数が正の整数の場合にのみ、それに加えて改行printf
が書き込まれ$l
ますstdout
。
read
チェックがループを少し複雑に別のループが呼び出された直後理由- for
引数を反復処理ループ2-$#
に表されるように$n
、親の各反復のためwhile
のループ。つまり、反復ごとに、最初の引数はコマンドラインで指定された値$_n
から1ずつ減らされる必要がありますが、他のすべての引数は元の値を保持する必要があるため、マーカーvarの値はそれぞれから差し引かれますが、最初の引数に0より大きい値。
これは関数のメインループを構成しますが、コードの大部分は先頭にあり、関数がパイプであっても入力としてクリーンにバッファーできるようにすることを目的としています。これは、最初にバックグラウンドdd
を呼び出して、出力のtmpfileに4k個のブロックサイズでコピーします。次に、関数はホールドループを設定します。これは、単一の完全なサイクルであってもほぼ完了しないはずdd
です。関数がそのstdinをtmpfileにリンクされたファイル記述子で置き換える前に、少なくとも1つのファイルへの書き込みを確実に行うためです。その後すぐにファイルのリンクを解除しますrm
。これにより、関数はトラップやクリーンアップを必要とせずにストリームを確実に処理できます。関数がfdで解放するとすぐに、名前付きのファイルシステムリンクのみがすでに削除されているため、tmpfileは存在しなくなります。
head
とtail
?もしそうなら、あなたのソリューションはあなたがすることができるほとんど最高です。他のプログラムの使用が許可されている場合、sed
またはawk
より優れたソリューションが許可されている場合(つまり、プロセス呼び出しが少ない場合)。