回答:
これらの行をホールドバッファーにコピーし(その後、削除し)、最後の行でホールドバッファーの内容をパターンスペースに追加します。
some command | sed '1,NUMBER{ # in this range
H # append line to hold space and
1h # overwrite if it's the 1st line
d # then delete the line
}
$G' # on last line append hold buffer content
ではgnu sed、あなたはとしてそれを書くことができます
some command | sed '1,NUMBER{H;1h;d;};$G'
次に、ol 'を使用した別の方法を示しますed(r出力をsome commandテキストバッファーにm送り、その後、最初の行の1,NUMBER後に行を移動します$)。
ed -s <<IN
r ! some command
1,NUMBERm$
,p
q
IN
指摘したように、出力がNUMBER+1行未満の場合、これらは両方とも失敗することに注意してください。より堅固なアプローチは(gnu sed構文)です:
some command | sed '1,NUMBER{H;1h;$!d;${g;q;};};$G'
これは、最後の行($!d)でない限り、その範囲の行のみを削除します。それ以外の場合は、パターンスペースをホールドバッファーの内容(g)で上書きし、次にquit(現在のパターンスペースの印刷後)を実行します。
sed -e '1,NUMBER{H;1h;d;}' -e '$G'また、移植性に動作し(いくつかのことに注意してくださいsedので、実装は、ホールドスペースで数キロバイト以上保持することはできませんNUMBERが大きすぎることはできませんが)
sed -e '1,NUMBER{H;1h;d' -e'}' -e '$G'ですか?
-eは改行を置き換えます。d;}まだPOSIXではありませんが、移植可能です。これは、次のPOSIX仕様で修正される予定です。参照してくださいaustingroupbugs.net/view.php?id=944#c2720
1,NUMBER{H;1h;d;}できないのは、オープニングブレースの直後にセミコロンがないことです。それは、SunOS 4.1のバグだったのかもしれませんが、sedその回避策は20年後も私の指に組み込まれています。
awkアプローチ:
cmd | awk -v n=3 '
NR <= n {head = head $0 "\n"; next}
{print}
END {printf "%s", head}'
@don_crisstiのsedアプローチに対する 1つの利点は、出力の行n数が少ない場合でも機能する(行を出力する)ことです。
\nれたORS を置き換えて、これが他のレコードセパレーターで機能するようにすることができます(たとえば、段落を使用したい場合など)。
私はxclipそれを持っているので、これはこのようにして行うことができます:
./a_command | xclip -in && xclip -o | tail -n +3 && xclip -o | head -n 2
ここにその説明があります:
xclip - command line interface to X selections (clipboard)
NAME
xclip - command line interface to X selections (clipboard)
SYNOPSIS
xclip [OPTION] [FILE]...
DESCRIPTION
Reads from standard in, or from one or more files, and makes the data available as an X selection for pasting into X applications. Prints current X selection to standard out.
-i, -in
read text into X selection from standard input or files (default)
-o, -out
prints the selection to standard out (generally for piping to a file or program)
Perlの方法:
perl -ne '$.<3?($f.=$_):print;}{print $f'
または、同じことをより不可解に記述します。
perl -ne 'if($.<3){ $f.=$_ } else{ print } END{print $f}'
例えば:
$ cat file
44444
55555
11111
22222
33333
$ cat file | perl -ne '$.<3?($f.=$_):print;}{print $f'
11111
22222
33333
44444
55555
-ne:入力ファイル/ストリーム-eを1行ずつ読み取り、指定されたスクリプトを各行に適用します。$.<3:$.は現在の行番号なので3、シフトする行数に変更します。$.<3?($f.=$_):print;:これは、条件演算子は、一般的な形式がある、あるcondition ? case1 : case2、それを実行するcase1場合はconditiontrueで、case2それが偽である場合。ここでは、現在の行番号が3未満の場合、現在の行($_)を変数に追加し$f、行番号が3より大きい場合は出力します。}{ print $f:}{はperlの省略形ですEND{}。すべての入力行が処理された後に実行されます。この時点で、シフトしたいすべての行が収集され、そのままにしたいすべての行が印刷されるので、として保存された行を印刷し$fます。perl -ne '$.<3?$f.=$_:print}{print $f
POSIXを使用しexます。はい、ファイルの編集を目的としていますが、パイプラインで機能します。
printf %s\\n 111 222 333 444 555 | ex -sc '1,2m$|%p|q!' /dev/stdin
これには、パイプラインの最初または最後に任意のコマンドを追加でき、同じように機能します。さらに、の存在を考えると、/dev/stdinPOSIXに準拠しています。
(/dev/stdinがPOSIXで指定されているかどうかはわかりませんが、LinuxとMac OS Xの両方に存在することがわかります。)
これには、sedのホールドスペースを使用する場合よりも読みやすくなるという利点があります。ex「これらの行を最後に移動する」と指示するだけで実行されます。(残りのコマンドは、「バッファを出力する」と「終了する」を意味し、どちらもかなり読みやすいです。)
注意:上記のexコマンドは、入力として2行未満の場合、失敗します。
参考文献:
短いpythonスニペット:
#!/usr/bin/env python3
import sys
file_ = sys.argv[1]
lines = int(sys.argv[2])
with open(file_) as f:
f = f.readlines()
out = f[lines:] + f[:lines]
print(''.join(out), end='')
ファイル名を最初の引数として渡し、移動する行数を2番目の引数として渡します。
例:
$ cat input.txt
44444
55555
11111
22222
33333
$ ./sw_lines.py input.txt 2
11111
22222
33333
44444
55555
$ ./sw_lines.py input.txt 4
33333
44444
55555
11111
22222
出力全体をメモリに保存できる場合:
data=$(some command)
n=42 # or whatever
{ tail -n +$((n+1)) <<<"$data"; head -n $n <<<"$data"; } > outputfile
GNUを必要とする別のオプションを次に示しますsed。
(x=$(gsed -u 3q);cat;printf %s\\n "$x")
-uコマンドがSTDINの3行以上を消費しないsedように、GNUをバッファーなしsedにします。コマンドの置換により空の行が削除されるため、3、3、2番目、または3、2、1番目の行が空の場合、コマンドの出力の最後に空の行は含まれません。
次のようなこともできます:
tee >(sponge /dev/stdout|sed -u 3q)|sed 1,3d
せずにsponge /dev/stdout|コマンド長い入力に失敗するでしょう。たとえば、入力が改行である場合に出力される場合でも、でsponge /dev/stdout置き換えることができます。または、入力の末尾から空の行を削除する場合tac|tacでも、で置き換えることができます。上記のコマンドは、入力の行数が1または2の場合、最初の行を削除します。a\ncba\nb\nc\n(x=$(cat);printf %s\\n "$x")