sed編集ファイルを配置


300

編集したコンテンツを手動で新しいファイルにストリーミングし、新しいファイルの名前を元のファイル名に変更せずに、単一のsedコマンドでファイルを編集できるかどうかを確認しようとしています。私はその-iオプションを試しましたが、私のSolarisシステムはそれ-iが違法なオプションだと言っていました。別の方法はありますか?


7
-ignu sedのオプションですが、標準sedにはありません。ただし、コンテンツを新しいファイルにストリーミングしてから、ファイルの名前を変更するため、希望どおりにはなりません。
ウィリアムパーセル

2
実際、それは私が望んでいることです。新しいファイルの名前を元の名前に変更するという平凡なタスクを実行する必要がないようにしたいだけです
両生類

3
次に、質問を再説明する必要があります。
ウィリアムパーセル

3
@amphibient:質問のタイトルの前に「Solaris」という単語を付けてもかまいませんか。あなたの質問の価値は失われつつあります。私の回答の下のコメントをご覧ください。ありがとう。
Steve

1
@Steve:Solaris専用ではないため、タイトルからSolarisプレフィックスを再度削除しました。
Tripleee、2016年

回答:


477

この-iオプションは、編集されたコンテンツを新しいファイルにストリーミングし、それを裏で名前を変更します。

例:

sed -i 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename

そして

sed -i '' 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename

上のMacOSの


3
少なくともそれは私のためにそれをするので私はする必要はありません
両生類

2
システムでGNU sedをコンパイルしようとするかもしれません。
チョロバ2012年

3
例:sed -i "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>
Thales Ceolin 2014

2
これはperlソリューションよりも優れています。どういうわけかそれは.swapファイルを作成しません....ありがとう!
数学

3
@maths:ありますが、おそらく他のどこか、またはより短い時間ですか?
チョロバ2014

72

sed適切な場所でファイルを編集する機能がないシステムでは、以下を使用する方がより良い解決策になると思いますperl

perl -pi -e 's/foo/bar/g' file.txt

これは一時ファイルを作成しますが、空の適切なサフィックス/拡張子が指定されているため、元のファイルを置き換えます。


14
一時ファイルを作成するだけでなく、ハードリンクも解除します(たとえば、ファイルの内容を変更する代わりに、ファイルを同じ名前の新しいファイルに置き換えます)。これは望ましい動作である場合があります。許容範囲内ですが、ファイルへのリンクが複数ある場合、ほとんどの場合、これは間違った動作です。
ウィリアムパーセル

3
@DwightSpencer:Perlのないシステムはすべて壊れていると思います。昇格されたアクセス許可が必要で、を使用する必要がある場合、単一のコマンドが一連のコマンドよりも優先されますsudo。私の考えでは、最新のGNUまたはBSDをインストールせずに一時ファイルを手動で作成して名前を変更しないようにする方法についての質問ですsed。Perlを使用するだけです。
Steve

4
@PetrPeller:本当に?質問を注意深く読むと、OPがのようなものを回避しようとしていることがわかりますsed 's/foo/bar/g' file.txt > file.tmp && mv file.tmp file.txt。インプレース編集が一時ファイルを使用して名前を変更するからといって、オプションが使用できない場合に手動で名前を変更する必要があるという意味ではありません。彼/彼女が望むことを行うことができる他のツールが世の中にあり、Perlは明白な選択です。これは元の質問に対する答えではないのですか?
Steve

2
@a_arias:その通りです。彼がやった。しかし、彼はSolarisを使用して彼が望むものを達成することができませんsed。質問は実際には非常に良いものでしたが、manページを読むことができないか、SOで実際に質問を読むことに煩わされない人々によって、その価値は減少しています。
Steve

4
@EdwardGarson:IIRC、SolarisにはPerlが同梱されていますが、PythonまたはRubyは同梱されていません。そして、私が以前に言ったように、OPはSolaris sedを使用して望ましい結果を達成することができません。
スティーブ

56

OS Xでは、このコマンドを実行すると、「無効なコマンドコード」などの奇妙なエラーやその他の奇妙なエラーが発生する場合があります。この問題を解決するには、

sed -i '' -e "s/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g" <file>

これは、OSXバージョンのsedでは-iオプションがextension引数を期待するため、コマンドは実際にはextension引数として解析され、ファイルパスはコマンドコードとして解釈されます。ソース:https : //stackoverflow.com/a/19457213


1
これは、幸いなOS Xの別の風変わりであるbrew install gnu-sedとともにはPATHあなたがのsedのGNUバージョンを使用できるようになります。言及していただきありがとうございます。明確な頭のスクラッチャー。
Doug

23

以下は私のMacで正常に動作します

sed -i.bak 's/foo/bar/g' sample

サンプルファイルでは、fooをbarに置き換えています。元のファイルのバックアップは、sample.bakに保存されます

バックアップなしでインライン編集するには、次のコマンドを使用します

sed -i'' 's/foo/bar/g' sample

バックアップファイルを保持しないようにする方法はありますか?
Petr Peller、2014

@PetrPeller、同じコマンドに上記のコマンドを使用できます... sed -i '' 's / foo / bar / g' sample
minhas23

18

もう一つ注意すべき、sedsedを唯一の目的として、独自に書き込み、ファイルできない「ストリーム」(つまり標準入力、標準出力、標準エラー出力、および他のパイプラインの編集者として働くことで>&n、バッファ、ソケットなど)。これを念頭に置いて、別のコマンドteeを使用して出力をファイルに書き戻すことができます。別のオプションは、コンテンツをにパイプしてパッチを作成することdiffです。

ティー方式

sed '/regex/' <file> | tee <file>

パッチ方式

sed '/regex/' <file> | diff -p <file> /dev/stdin | patch

更新:

また、patchはファイルをdiff出力の1行目から変更することに注意してください。

これはdiffからの出力の最初の行にあるため、パッチはどのファイルにアクセスするかを知る必要はありません。

$ echo foobar | tee fubar

$ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin
*** fubar   2014-03-15 18:06:09.000000000 -0500
--- /dev/stdin  2014-03-15 18:06:41.000000000 -0500
***************
*** 1 ****
! foobar
--- 1 ----
! fubar

$ sed 's/oo/u/' fubar | diff -p fubar /dev/stdin | patch
patching file fubar

2
/dev/stdin 2014-03-151月7日の回答 -あなたはタイムトラベラーですか?
エイドリアンFrühwirth14年

Windowsでは、msysgitを使用して、/dev/stdinあなたは交換する必要がありますので、存在しません/dev/stdin:「 - 」で以下のコマンドが動作するはずですので、引用符、ハイフンを$ sed 's/oo/u/' fubar | diff -p fubar -して$ sed 's/oo/u/' fubar | diff -p fubar - | patch
ジム・螺鈿

@AdrianFrühwirth私はどこかに青い交番を持っています、そして、何らかの理由で彼らは私を医者と呼んでいます。しかし、正直なところ、その時点でシステムのクロックドリフトが本当に悪いようです。
ドワイトスペンサー

これらのソリューションは、特定のバッファリング動作に依存しているように見えます。sedが読み取りを行っている間、これらのファイルが壊れる可能性があるのではないかと疑っています。ファイルは、patchコマンドによってその下から変化し始める場合があり、さらに悪いことに、ファイルを切り捨てるteeコマンドによって変化する場合もあります。実際にpatch切り捨てられないかどうかはわかりません。出力を別のファイルに保存してから、cat元のファイルに保存する方が安全だと思います。
akostadinov 2016年

@ william-pursellからの実際のインプレイス回答
akostadinov

11

あなたが望むことをすることは不可能ですsedsedその-i場でファイルを編集するオプションをサポートするバージョンでも、明示的に望まないことを実行します。一時ファイルに書き込み、ファイルの名前を変更します。しかし、おそらくあなたは単に使用することができますed。たとえば、ファイル内のすべての出現をに変更fooするbarにはfile.txt、次のようにします。

echo ',s/foo/bar/g; w' | tr \; '\012' | ed -s file.txt

構文はに似ています sedいますが、完全に同じではありません。

ただし、名前を変更した一時ファイルを使用しない理由を検討する必要があるかもしれません。-iサポートがない場合でも、sed簡単にスクリプトを作成して作業を行うことができます。代わりにsed -i 's/foo/bar/g' file、あなたがすることができますinline file sed 's/foo/bar/g'。このようなスクリプトを書くのは簡単です。例えば:

#!/bin/sh -e
IN=$1
shift
trap 'rm -f $tmp' 0
tmp=$( mktemp )
<$IN "$@" >$tmp && cat $tmp > $IN  # preserve hard links

ほとんどの用途に適しています。


1
たとえば、このスクリプトにどのように名前を付け、どのように呼び出すのでしょうか。
両生類、

2
私はそれを呼ぶだろうinlineし、それを呼び出すように、上記説明:inline inputfile sed 's/foo/bar/g'
ウィリアムPursell

1
うわー、ed本当にその場で行う答えのみ。初めて必要edです。ありがとうございました。少しの最適化は、使用するecho -e ",s/foo/bar/g\012 w"echo $',s/foo/bar/g\012 w'、シェルが余分なtr呼び出しを回避できるようにする場所です。
akostadinov 2016年

2
ed変更は実際には行われません。strace出力から、GNU edは一時ファイルを作成し、変更を一時ファイルに書き込んでから、ハードリンクを保持しながら元のファイル全体を書き換えます。truss出力から、Solaris 11 edは一時ファイルも使用しますが、wコマンドを使用して保存すると、一時ファイルの名前を元のファイル名に変更し、ハードリンクを破棄します。
Andrew Henle

@AndrewHenle残念です。ed現在のMacOS(モハーベ、何でもそのマーケティングの専門用語の意味)と船がまだハードリンクを保持していること。YMMV
ウィリアムパーセル

10

あなたはviを使うことができます

vi -c '%s/foo/bar/g' my.txt -c 'wq'

9

sedはインプレース編集をサポートしています。からman sed

-i[SUFFIX], --in-place[=SUFFIX]

    edit files in place (makes backup if extension supplied)

hello.txtのテキストを含むファイルがあるとします。

hello world!

古いファイルのバックアップを保持したい場合は、以下を使用します。

sed -i.bak 's/hello/bonjour' hello.txt

最終的に2つのファイルが作成されます。hello.txt内容は次のとおりです。

bonjour world!

そしてhello.txt.bak古い内容で。

コピーを保持したくない場合は、extensionパラメータを渡さないでください。


3
OPは、彼のプラットフォームがこの(人気のある)非標準オプションをサポートしていないことを具体的に述べています。
Tripleee、2016年

3

使用しているシェルを指定しませんでしたが、zshを使用すると、=( )構成を使用してこれを実現できます。以下の線に沿った何か:

cp =(sed ... file; sync) file

=( )に似て>( )いますが、cp終了時に自動的に削除される一時ファイルを作成します。


3
mv file.txt file.tmp && sed 's/foo/bar/g' < file.tmp > file.txt

すべてのハードリンクを保持する必要があります。出力は元のファイルの内容を上書きするように戻され、特別なバージョンのsedの必要性を回避するためです。


3

同じ量の文字を置き換え、ファイルの「インプレース」編集を注意深く読んだ後の場合 ...

リダイレクト演算子<>を使用して、ファイルを開いて読み書きすることもできます。

sed 's/foo/bar/g' file 1<> file

ライブで見る:

$ cat file
hello
i am here                           # see "here"
$ sed 's/here/away/' file 1<> file  # Run the `sed` command
$ cat file
hello
i am away                           # this line is changed now

Bashリファレンスマニュアルから→3.6.10読み取りおよび書き込み用にファイル記述子を開く

リダイレクト演算子

[n]<>word

ワードの拡張である名前のファイルが、ファイル記述子nで、またはnが指定されていない場合はファイル記述子0で、読み取りと書き込みの両方のために開かれます。ファイルが存在しない場合は作成されます。


これはファイルによって破損しています。その理由はよくわかりません。paste.fedoraproject.org/462017
Nehal J Wani

行[43-44]、[88-89]、[135-136]を参照
Nehal J Wani

2
このブログ記事では、この回答を使用しない理由を説明しています。backreference.org/2011/01/29/in-place-editing-of-files
Nehal Jワニ

@NehalJWaniヘッドアップしてくれてありがとう!私が回答で触れなかったのは、これが同じ量の文字を変更する場合に機能することです。
fedorqui「SO害をやめる」

@NehalJWaniこれは言われていますが、私の答えがあなたのファイルに害を与えた場合は申し訳ありません。提供されたリンクを読んだ後、修正して更新します(または必要に応じて削除します)。
fedorqui「SO害をやめる」

2

MoneypennyがSkyfallで言ったように:「時々古い方法が最善です。」キンケードは後で同様のことを言った。

$ printf ',s/false/true/g\nw\n' | ed {YourFileHere}

適切な編集を行います。ファイルを書き込むために「\ nw \ n」を追加しました。リクエストへの回答の遅延についてお詫びします。


これが何をするか説明できますか?
Matt Montag、2018年

1
これはed(1)を呼び出します。これは、stdinに書き込まれたいくつかの文字を含むテキストエディターです。30歳未満の人として、恐竜と同じようにed(1)が恐竜にあると言っても大丈夫だと思います。とにかく、edletを開いて入力する代わりに、jlettvinはを使用して文字をパイプし|ます。@MattMontag
Ari Sweedler、2018

コマンドの機能を確認する場合、2つのコマンドがあり、で終了します\n。[範囲] s / <old> / <new> / <flag>は代替コマンドの形式です-他の多くのテキストエディタでまだ見られるパラダイム(そう、vim、edの直接の子孫)とにかく、gフラグは「グローバル」、および「あなたが見る各行のすべてのインスタンス」を意味します。範囲3,5は3〜5行目です。,5StartOfFile-5、3 3,行目からEndOfFile、,StartOfFile-EndOfFileを確認します。「false」を「true」に置き換える、すべての行のグローバル置換コマンド。次に、書き込みコマンドwが入力されます。
Ari Sweedler、2018

1

非常に良い例です。多くのファイルをインプレイス編集するという課題があり、-iオプションがfindコマンド内でそれを使用する唯一の合理的な解決策のようです。ここで、各ファイルの最初の行の前に「バージョン:」を追加するスクリプト:

find . -name pkg.json -print -exec sed -i '.bak' '1 s/^/version /' {} \;
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.