POSIXで指定されていない-iフラグの代わりにw(write)コマンドを使用して、sedを使用してファイルを内部で編集できますか?

POSIXで指定されていない-iフラグの代わりにw(write)コマンドを使用して、sedを使用してファイルを内部で編集できますか?

w私のコマンド(macOS 13.1のsed)は、(bash 3.2)を使って入力ファイルを編集sedできるようです。cat

printf "hello\nworld\n" > foo.txt

cat foo.txt | sed 's/l/L/g' | sed -n 'w foo.txt'

cat foo.txt
> heLLo
> worLd

私は見たhttps://pubs.opengroup.org/onlinepubs/9699919799/utilities/sed.htmlしかし、リダイレクトなどをfoo.txt使用する場合とは異なり、上記のパイプラインを正常に編集できる理由は何であるかよくわかりません。cat foo.txt | sed 's/l/L/g' > foo.txt

POSIX指定されていないフラグまたは一時ファイルが利用可能であることを知っていますが、(書き込み)コマンドを使用して入力ファイルを編集するのが安全かどうかを知りたいです-iw

編集する:

頑張った

printf "%d hello world\n" {1..100000} > foo.txt

cat foo.txt | sed 's/l/L/g' | sed -n 'w foo.txt'

もう正常に動作しないことがわかりました。結果はfoo.txt4000〜8000行にすぎません。

ベストアンサー1

使用sponge(からその他のユーティリティまたは一時ファイルにリダイレクトし、元のファイルに名前を変更します。または使用編集する(またはexvi/vim/nviで)sed- 覚えておいてください。これはsedストリーム指向バージョンですeded= editorsed=小川編集する。

注:ed、sed、ex(そしてvi - viはもともとedのフルバージョン)はすべて共通のルートを持っているので、共通コマンドのサブセットを共有します。しかし、それぞれが異なる方向に開発され、異なる拡張機能を持っています。それぞれ異なる機能を持ついくつかのバージョンがあります。他の多くのプログラムは少なくともいくつかの共通コマンドを借用しました(たとえば、rogueとnethackは両方hjkl移動キーを借用しました)。明確でない場合でも注目に値する。exコマンドは:vi内のコマンドであり、コマンドの親セットです(使用する実装edによって異なります)。vi

3つの方法すべての例です。

sed -e 's/l/L/g' foo.txt | sponge foo.txt

sed -e 's/l/L/g' foo.txt > foo.new && mv foo.new foo.txt

printf '%s\n' %s/l/L/g w q | ed -s foo.txt
printf '%s\n' %s/l/L/g w q | ex foo.txt

ところで、ソースman sponge

sponge標準入力を読み取り、指定されたファイルに書き込みます。シェルリダイレクトとは異なり、スポンジは出力ファイルに書き込む前にすべての入力を吸収します。これにより、同じファイルを読み書きするパイプラインを構築できます。

出力ファイルがすでに存在する場合、Sponge はファイルの権限を保持します。

メモ:

  1. Spongeは基本的にメソッドをリダイレクトして名前を変更する便利なツールです。

  2. リダイレクトと名前変更は、ソース出力ファイルの権限を保持しません。ユーザーが決定した権限で新しいファイルを生成しますumask(他の作成した新しいファイルと同様)。 umaskによっては、これらの権限は元の権限と同じでも同じでもない場合があります。

    違いは次のとおりです。sponge 確実にする新しいファイルには元のファイルと同じ権限がありますが、単純なリダイレクトではありません。

  3. and を使用するedと、ex各コマンド ( write および finally quit でs///置き換えられる ) が 1 行に 1 つずつ印刷され、 or にパイプされて foo.txt を開き、コマンドを実行します。wqprintf '%s\n'edex


また、注:ed両方exとも元のファイルを上書きします(元のファイルのinode番号を保持するため、そのファイルへのハードリンクは壊れません)。 sponge一時ファイルへの書き込みと名前変更は、異なるinode番号を持つ新しいファイルを生成するため、ハードリンクが壊れます。ほとんどの場合(つまり、1つ以上のファイルへのハードリンクがない場合)、これはまったく重要ではありませんが、知っておくべきことです。

たとえば、次のようにinode番号がどのように変更されるかを確認しますsponge

$ printf "hello\nworld\n" > foo.txt
$ ls -li foo.txt
2251637 -rw-rw-r-- 1 cas cas 12 Feb  6 18:07 foo.txt
$ sed -e 's/l/L/g' foo.txt | sponge foo.txt
$ ls -li foo.txt
2251985 -rw-rw-r-- 1 cas cas 12 Feb  6 18:07 foo.txt

リダイレクトでファイルを上書きしても、inode番号は変更されず、ex(またはed)で編集されません。

$ printf "hello\nworld\n" > foo.txt
$ ls -li foo.txt
2251985 -rw-rw-r-- 1 cas cas 12 Feb  6 18:08 foo.txt
$ printf '%s\n' %s/l/L/g w q | ex foo.txt 
$ ls -li foo.txt
2251985 -rw-rw-r-- 1 cas cas 12 Feb  6 18:09 foo.txt

必要に応じて、次のようにリダイレクトと名前変更方法を使用して元のインデックスノードを保存できます。

sed -e 's/l/L/g' foo.txt > foo.new
cat foo.new > foo.txt
rm foo.new

catはい、それは必要ではないことを知っています。<タスクもリダイレクトします。私は、コマンドラインの先頭からリダイレクトしたり、実際のコマンドなしでリダイレクトしたりするのが嫌だと思っています。連合大学

そしてStephen Kittがコメントで指摘したように、cp foo.new foo.txtこの機能も機能し、元の権限をそのまま維持します。

おすすめ記事