巨大なファイルの最初と最後に行を追加するシナリオがあります。
以下のようにしてみました。
最初の行:
sed -i '1i\'"$FirstLine" $Filename
最後の行:
sed -i '$ a\'"$Lastline" $Filename
しかし、このコマンドの問題は、ファイルの最初の行を追加し、ファイル全体をトラバースすることです。最後の行では、再びファイル全体を走査し、最後の行を追加しています。非常に大きなファイル(14GB)なので、これには非常に長い時間がかかります。
ファイルを1回だけ読み取るときに、ファイルの最初と最後に行を追加するにはどうすればよいですか?
sed -i
は、実装の詳細として一時ファイルを使用しています。これは、実際に発生していることです。ただし、既存のコンテンツを上書きせずにデータストリームの先頭にデータを追加するには、ファイルを書き換える必要があります。sed -i
を回避したとしても、それを回避する方法はありません。
ファイルの再書き込みができない場合は、次のように、ファイルを読み取るときに操作することを検討してください。
{ echo some prepended text ; cat file ; } | command
また、sedはストリームの編集用です-ファイルはストリームではありません。 edやexなど、この目的のためのプログラムを使用してください。 sedの-i
オプションは移植性が高いだけでなく、基本的にファイルを削除して再作成するため、ファイルへのシンボリックリンクも破壊されますが、これは無意味です。
次のように、ed
を使用して単一のコマンドでこれを行うことができます。
ed -s file << 'EOF'
0a
prepend these lines
to the beginning
.
$a
append these lines
to the end
.
w
EOF
Edの実装によっては、ページングファイルを使用する場合があるため、少なくとも使用可能なスペースを確保する必要があることに注意してください。
ファイルのコピー全体をディスクに割り当てないようにする場合は、次のようにすることができます。
sed '
1i\
begin
$a\
end' < file 1<> file
これは、そのstdin/stdoutがファイルの場合、sed
がブロックごとに読み書きするという事実を利用しています。したがって、ここでは、追加する最初の行がsed
のブロックサイズ(4kまたは8kのようなもの)より小さい限り、読み取っているファイルを上書きしても問題ありません。
なんらかの理由でsed
が失敗した場合(強制終了、マシンクラッシュ...)、ファイルが半分処理されることに注意してください。これは、途中のどこかで最初の行のサイズのデータが欠落していることを意味します。
また、sed
がGNU sed
でない限り、バイナリデータでは機能しません(ただし、-i
、GNU sed)を使用しています。
ここにいくつかの選択肢があります(すべてがファイルの新しいコピーを作成するので、そのための十分なスペースがあることを確認してください):
シンプルなエコー/猫
echo "first" > new_file; cat $File >> new_file; \
echo "last" >> new_file;
awk/gawkなど
gawk 'BEGIN{print "first\n"}{print}END{print "last\n"}' $File > NewFile
awk
とそのilkは、ファイルを1行ずつ読み取ります。 BEGIN{}
ブロックは最初の行の前に実行され、END{}
ブロックは最後の行の後に実行されます。したがって、上記のコマンドはprint "first" at the beginning, then print every line in the file and print "last" at the end
を意味します。
Perl
Perl -ne 'BEGIN{print "first\n"} print;END{print "last\n"}' $File > NewFile
これは基本的に、Perlで記述された上記のgawkと同じです。
私はずっと単純なほうを好みます:
gsed -i '1s/^/foo\n/gm; $s/$/\nbar/gm' filename.txt
これはファイルを変換します:
asdf
qwer
ファイルへ:
foo
asdf
qwer
bar
ファイルの先頭にデータを挿入する方法はありません。新しいファイルを作成し、追加のデータを書き込んで、古いデータを追加するだけです。したがって、最初の行を挿入するには、ファイル全体を少なくとも1回書き換える必要があります。ただし、ファイルを書き換えずに最後の行を追加できます。
sed -i '1i\'"$FirstLine" $Filename
echo "$LastLine" >>$Filename
または、sedの1回の実行で2つのコマンドを組み合わせることができます。
sed -i -e '1i\'"$FirstLine" -e '$ a\'"$Lastline" $Filename
sed -i
は新しい出力ファイルを作成し、それを古いファイルの上に移動します。これは、sedが動作している間、スペースを使い切ったファイルの2番目のコピーがあることを意味します。これは ファイルを上書きする で回避できますが、大きな制限があります。追加する行はsedのバッファーよりも小さくする必要があり、システムがクラッシュした場合、結果として破損します。ファイルと一部のコンテンツが途中で失われるので、これはお勧めしません。
¹ Linuxにはデータをファイルに挿入する方法はありますが、挿入できるのはファイルシステムブロックの整数だけであり、任意の長さの文字列を挿入することはできません。データベースや仮想マシンなどの一部のアプリケーションには役立ちますが、テキストファイルには役に立ちません。
VimはExモードで使用できます。
ex -sc '1i|ALFA' -c '$a|BRAVO' -cx file
1
最初の行を選択
i
テキストと改行を挿入
$
最後の行を選択
a
テキストと改行を追加
x
保存して閉じる
$ (echo "Some Text" ; cat file1) > file2