111

sortbashのコマンドでソートしたいファイルtemp.txtがあります。

並べ替えた結果で元のファイルを置き換えたい。

たとえば、これは機能しません (空のファイルを取得します):

sortx temp.txt > temp.txt

一時ファイルへのコピーに頼らずに、これを 1 行で実行できますか?


編集: この-oオプションは にとって非常にクールですsortsort例として質問で使用しました。他のコマンドでも同じ問題が発生します。

uniq temp.txt > temp.txt.

より良い一般的な解決策はありますか?

4

14 に答える 14

170
sort temp.txt -o temp.txt
于 2008-09-28T18:45:41.410 に答える
29

Asortは、出力を開始する前にすべての入力を確認する必要があります。このため、sortプログラムはファイルをその場で変更するオプションを簡単に提供できます。

sort temp.txt -o temp.txt

具体的には、GNU のドキュメントにsortは次のように書かれています。

通常、 sort は output-file を開く前にすべての入力を読み取るため、sort -o F Fや などのコマンドを使用してファイルを安全にソートできますcat F | sort -o F。ただし、sortwith --merge( -m) はすべての入力を読み取る前に出力ファイルを開くことができるため、 sort のようなコマンドは、読み取りが完了する前にcat F | sort -m -o F - G書き込みを開始する可能性があるため安全ではありません。Fcat

BSDのドキュメントには次のように書かれていますがsort

[the] output-file が入力ファイルの 1 つである場合、sort はそれを一時ファイルにコピーしてから、出力をソートして [the] output-file に書き込みます。

などのコマンドuniqは、入力の読み取りが完了する前に出力の書き込みを開始できます。これらのコマンドは通常、インプレース編集をサポートしていません (この機能をサポートするのはより困難です)。

通常、一時ファイルを使用してこれを回避するか、中間ファイルを絶対に避けたい場合は、バッファを使用して完全な結果を保存してから書き出すことができます。たとえば、次の場合perl:

uniq temp.txt | perl -e 'undef $/; $_ = <>; open(OUT,">temp.txt"); print OUT;'

ここで、perl 部分はuniqin 変数から完全な出力を読み取り$_、元のファイルをこのデータで上書きします。選択したスクリプト言語、おそらく Bash でも同じことができます。ただし、ファイル全体を格納するのに十分なメモリが必要になることに注意してください。これは、大きなファイルを扱う場合にはお勧めできません。

于 2008-09-29T07:40:28.537 に答える
19

これはより一般的なアプローチであり、uniq、sort などで動作します。

{ rm file && uniq > file; } < file
于 2010-12-10T22:39:27.947 に答える
11

スポンジに関する東武のコメントは、それ自体が答えであることを保証します。

moreutilsのホームページから引用するには:

おそらく、これまでの moreutils で最も汎用的なツールは、sponge(1) で、次のようなことができます。

% sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd

ただし、Steve Jessop がここでコメントしているspongeのと同じ問題に苦しんでいます。前のパイプラインのコマンドのいずれかが失敗した場合、元のファイルは上書きされます。sponge

$ mistyped_command my-important-file | sponge my-important-file
mistyped-command: command not found

う~ん、my-important-fileなくなった。

于 2013-07-05T14:49:13.847 に答える
6

ほら、1行:

sort temp.txt > temp.txt.sort && mv temp.txt.sort temp.txt

技術的には、一時ファイルへのコピーはなく、'mv' コマンドは即座に実行されるはずです。

于 2008-09-28T18:35:10.390 に答える
4

多くの人が-oオプションについて言及しています。これがmanページの部分です。

マニュアルページから:

   -o output-file
          Write output to output-file instead of to the  standard  output.
          If  output-file  is  one of the input files, sort copies it to a
          temporary file before sorting and writing the output to  output-
          file.
于 2008-09-28T20:01:31.043 に答える
4

答えは気に入っていsort file -o fileますが、同じファイル名を 2 回入力したくありません。

BASH履歴拡張の使用:

$ sort file -o !#^

を押すと、現在の行の最初の引数を取得しますenter

その場での一意の並べ替え:

$ sort -u -o file !#$

現在の行の最後の引数を取得します。

于 2013-07-11T21:22:10.527 に答える
3

spongeより一般的なの代替sed:

sed -ni r<(command file) file

任意のコマンド ( sortuniqtac、...) で機能し、非常によく知られているsed-iオプション(ファイルをその場で編集) を使用します。

警告:command fileファイルのインプレース編集は本質的に安全ではないため、最初に試してください。


説明

まず、sed(元の) 行を印刷しないように指示し (-nオプションsed)、のrコマンドbashProcess Substitutionの助けを借りて、によって生成されたコンテンツがその場所に<(command file)保存された出力になります。


物事をさらに簡単に

このソリューションを関数にラップできます。

ip_cmd() { # in place command
    CMD=${1:?You must specify a command}
    FILE=${2:?You must specify a file}
    sed -ni r<("$CMD" "$FILE") "$FILE"
}

$ cat file
d
b
c
b
a

$ ip_cmd sort file
$ cat file
a
b
b
c
d

$ ip_cmd uniq file
$ cat file
a
b
c
d

$ ip_cmd tac file
$ cat file
d
c
b
a

$ ip_cmd
bash: 1: You must specify a command
$ ip_cmd uniq
bash: 2: You must specify a file
于 2015-01-17T16:10:11.027 に答える
3

これはメモリの制約が大きくなりますが、awk を使用して中間データをメモリに保存し、書き戻すことができます。

uniq temp.txt | awk '{line[i++] = $0}END{for(j=0;j<i;j++){print line[j]}}' > temp.txt
于 2008-09-29T13:40:27.907 に答える
2

非対話型エディタについて読んでくださいex

于 2008-09-28T18:33:38.570 に答える
1

引数を使用する--output=か、-o

FreeBSDで試してみました:

sort temp.txt -otemp.txt
于 2008-09-28T18:49:19.763 に答える
1

機能を追加するにuniqは、次の欠点があります。

sort inputfile | uniq | sort -o inputfile
于 2010-03-17T14:50:24.960 に答える
0

プログラムの使用を主張する場合は、中間ファイルを使用する必要があります-メモリ内でソートするオプションsortはないと思います。sortソートの標準入力のバッファサイズがファイル全体に十分に収まる大きさであることを保証できない限り、標準入力/標準出力を使用した他のトリックは失敗します。

編集:恥ずかしい。sort temp.txt -o temp.txt優れた作品。

于 2008-09-28T18:49:35.210 に答える
0

別の解決策:

uniq file 1<> file
于 2016-07-27T10:49:15.570 に答える