394

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

4

15 に答える 15

647

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

例:

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

macOS では次のものが必要です。

sed -i '' 's/STRING_TO_REPLACE/STRING_TO_REPLACE_IT/g' filename
于 2012-10-02T18:39:16.783 に答える
83

sedファイルをその場で編集する機能がないシステムでは、より良い解決策は次を使用することだと思いますperl

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

これにより一時ファイルが作成されますが、空のインプレース サフィックス/拡張子が指定されているため、元のファイルが置き換えられます。

于 2012-10-03T02:01:06.437 に答える
66

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

于 2015-01-29T03:48:59.690 に答える
30

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

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

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

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

sed -i'' 's/foo/bar/g' sample
于 2014-07-03T09:14:41.513 に答える
20

sedsed の唯一の目的は「ストリーム」(つまり、stdin、stdout、stderr、およびその他の>&nバッファー、ソケットなどのパイプライン) でエディターとして機能することであるため、ファイルを単独で書き込むことはできません。これを念頭に置いて、別のコマンドteeを使用して出力をファイルに書き戻すことができます。もう 1 つのオプションは、コンテンツを にパイプしてパッチを作成することdiffです。

ティー法

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

パッチ法

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

アップデート:

また、パッチは差分出力の 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
于 2014-01-07T00:11:11.347 に答える
16

そのバージョンは、ファイルをその場で編集するsedためのオプションをサポートしており-i、一時ファイルに書き込んでからファイルの名前を変更します。

または、を使用することもできますed。たとえば、ファイル内のfootoのすべての出現箇所を変更するには、次のようにします。barfile.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
IN=$1
shift
trap 'rm -f "$tmp"' 0
tmp=$( mktemp )
<"$IN" "$@" >"$tmp" && cat "$tmp" > "$IN"  # preserve hard links

ほとんどの用途に適しているはずです。

于 2012-10-02T19:03:51.793 に答える
10

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古い内容で。

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

于 2015-07-17T21:55:19.920 に答える
5

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

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

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

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

于 2016-08-25T11:26:01.103 に答える
3
mv file.txt file.tmp && sed 's/foo/bar/g' < file.tmp > file.txt

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

于 2015-08-11T00:31:51.623 に答える
3

使用しているシェルを指定しませんでしたが、zsh を使用すると、=( )構造を使用してこれを実現できます。次のようなもの:

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

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

于 2012-10-02T19:09:48.560 に答える
1

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

find . -name pkg.json -print -exec sed -i '.bak' '1 s/^/version /' {} \;
于 2015-02-07T11:00:46.847 に答える