回答:
これらの行をホールドバッファーにコピーし(その後、削除し)、最後の行でホールドバッファーの内容をパターンスペースに追加します。
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
)で上書きし、次にq
uit(現在のパターンスペースの印刷後)を実行します。
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
場合はcondition
trueで、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/stdin
POSIXに準拠しています。
(/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\ncb
a\nb\nc
\n
(x=$(cat);printf %s\\n "$x")