ファイルを編集するコマンド(引数)“ inplace”を実行する方法bashを使用していますか?
-
02-07-2019 - |
質問
ファイルtemp.txtがあり、bashの sort
コマンドでソートしたい。
ソートされた結果で元のファイルを置き換えたい。
これは、たとえば機能しません(空のファイルを取得します):
sortx temp.txt > temp.txt
これを一時ファイルにコピーせずに1行で実行できますか?
編集: -o
オプションは、 sort
にとって非常に便利です。例として質問で sort
を使用しました。他のコマンドでも同じ問題が発生します:
uniq temp.txt > temp.txt.
より良い一般的な解決策はありますか?
解決
sort temp.txt -o temp.txt
他のヒント
A sort
は、出力を開始する前にすべての入力を確認する必要があります。このため、 sort
プログラムは、ファイルをその場で変更するオプションを簡単に提供できます。
sort temp.txt -o temp.txt
具体的には、 GNU sortのドキュメント
のコメント:
通常、sortはoutput-fileを開く前にすべての入力を読み取るため、
sort -o F F
やcat F | sort -o F
。ただし、-merge
(-m
)を指定したsort
は、すべての入力を読み取る前に出力ファイルを開くことができるため、cat F | sort -m -o F-G
は、cat
が読み取りを完了する前にF
の書き込みを開始する可能性があるため、安全ではありません。
BSDのドキュメントには、 sort
には次のように書かれています:
[the] output-fileが入力ファイルの1つである場合、sortは、出力をソートして[the] output-fileに書き込む前に一時ファイルにコピーします。
uniq
などのコマンドは、入力の読み取りを完了する前に出力の書き込みを開始できます。通常、これらのコマンドはインプレース編集をサポートしていません(そして、この機能をサポートするのはより困難です)。
通常、一時ファイルを使用してこの問題を回避します。または、中間ファイルを絶対に避けたい場合は、バッファを使用して完全な結果を保存してから書き出すことができます。たとえば、 perl
:
uniq temp.txt | perl -e 'undef $/; A sort
は、出力を開始する前にすべての入力を確認する必要があります。このため、 sort
プログラムは、ファイルをその場で変更するオプションを簡単に提供できます。
sort temp.txt -o temp.txt
具体的には、 GNU sortのドキュメント
のコメント:
通常、sortはoutput-fileを開く前にすべての入力を読み取るため、 sort -o F F
や cat F | sort -o F
。ただし、-merge
( -m
)を指定した sort
は、すべての入力を読み取る前に出力ファイルを開くことができるため、 cat F | sort -m -o F-G
は、 cat
が読み取りを完了する前に F
の書き込みを開始する可能性があるため、安全ではありません。
BSDのドキュメントには、 sort
には次のように書かれています:
[the] output-fileが入力ファイルの1つである場合、sortは、出力をソートして[the] output-fileに書き込む前に一時ファイルにコピーします。
uniq
などのコマンドは、入力の読み取りを完了する前に出力の書き込みを開始できます。通常、これらのコマンドはインプレース編集をサポートしていません(そして、この機能をサポートするのはより困難です)。
通常、一時ファイルを使用してこの問題を回避します。または、中間ファイルを絶対に避けたい場合は、バッファを使用して完全な結果を保存してから書き出すことができます。たとえば、 perl
:
の場合
<*>
ここで、perl部分は変数 $ _
の uniq
から完全な出力を読み取り、このデータで元のファイルを上書きします。お好みのスクリプト言語でも、おそらくBashでも同じことができます。ただし、ファイル全体を保存するのに十分なメモリが必要になることに注意してください。大きなファイルを扱う場合はお勧めできません。
= <>; open(OUT,">temp.txt"); print OUT;'
ここで、perl部分は変数 $ _
の uniq
から完全な出力を読み取り、このデータで元のファイルを上書きします。お好みのスクリプト言語でも、おそらくBashでも同じことができます。ただし、ファイル全体を保存するのに十分なメモリが必要になることに注意してください。大きなファイルを扱う場合はお勧めできません。
これはより一般的なアプローチであり、uniq、sort、その他で動作します。
{ rm file && uniq > file; } < file
スポンジに関する東武のコメントは、それ自体が答えであることを保証します。
moreutils ホームページから引用するには:
おそらくこれまでのmoreutilsの最も汎用的なツールはsponge(1)で、次のようなことができます:
% sed "s/root/toor/" /etc/passwd | grep -v joey | sponge /etc/passwd
ただし、 sponge
には同じ問題があります Steve Jessopがここにコメントします。 sponge
が失敗する前にパイプライン内のコマンドの一部は、元のファイルが上書きされます。
$ mistyped_command my-important-file | sponge my-important-file
mistyped-command: command not found
うーん、 my-important-file
はなくなりました。
次の行に進みます:
sort temp.txt > temp.txt.sort && mv temp.txt.sort temp.txt
技術的には、一時ファイルへのコピーはなく、「mv」コマンドは即座に実行されます。
sort file -o file
の回答が好きですが、同じファイル名を2回入力したくありません。
BASHの使用履歴展開:
$ sort file -o !#^
enter を押すと、現在の行の最初の引数を取得します。
インプレースでのユニークなソート:
$ sort -u -o file !#$
現在の行の最後の引数を取得します。
多くの人が -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.
これは非常にメモリに制約がありますが、awkを使用して中間データをメモリに保存してから書き戻すことができます。
uniq temp.txt | awk '{line[i++] = <*>}END{for(j=0;j<i;j++){print line[j]}}' > temp.txt
より一般的な sed
による sponge
の代替:
sed -ni r<(command file) file
任意のコマンド( sort
、 uniq
、 tac
、...)で動作し、よく知られている sedを使用します
の -i
オプション(インプレースでファイルを編集)。
警告:ファイルをその場で編集することは本質的に安全ではないため、最初に command file
を試してください。
説明
まず、(元の)行を印刷しないように sed
に伝えています( -n
オプション)、および sed
の r
コマンドおよび bash
のプロセスの置換、&lt;(コマンドファイル)
は、インプレースに保存される出力になります。
物事をさらに簡単にする
このソリューションを関数にラップできます:
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
引数-output =
または -o
FreeBSDで試したところ:
sort temp.txt -otemp.txt
uniq
機能を追加するには、次の欠点があります:
sort inputfile | uniq | sort -o inputfile
非対話型エディター、 ex コード>
。
sort
プログラムの使用を主張する場合は、中間ファイルを使用する必要があります。 sort
にはメモリ内でソートするオプションはないと思います。ソートのstdinのバッファーサイズがファイル全体に収まる大きさであることを保証できない限り、stdin / stdoutを使用したその他のトリックは失敗します。
編集:恥を知れ。 sort temp.txt -o temp.txt
は優れた動作をします。
別の解決策:
uniq file 1<> file