Solarisの「sed -i」コマンドに代わるものはありますか?


11

私のプロジェクトでは、ファイル内の既存のテキストをfoo次のような他のテキストに置き換える必要がありますfooofoo

abc.txt
name
foo
foo1

だから私は試しました:

sed -i "s/foo/fooofoo/g" abc.txt

しかし、私はこのエラーを受け取ります:

sed:不正なオプション- i

私は使用しなければならないことをマニュアルで見つけました:

sed -i\ "s/foo/fooofoo/g" abc.txt

ただし、これも機能しません。

私は中の選択肢を発見したperlawkもなく、Solarisの溶液をsedはるかに高く評価されるだろう。

私はこのバージョンのbashを使用しています:

GNU bash、バージョン3.2.57(1)-release(sparc-sun-solaris2.10)


Solaris 11以降では、単に/usr/gnu/bin/sed-iサポートを取得するために使用します。
アラン

回答:


15

を使用しedます。ほとんどのプラットフォームで利用でき、ファイルをその場で編集できます。
以来sedに基づいてedパターンを交換するための構文と似ています。

ed -s infile <<\IN
,s/old/new/g
w
q
IN

なぜのed代わりにex、単に興味があるのですか?(私は両方ともPOSIX準拠であり、仕様にリンクしていることを知っています。))
ワイルドカード

1
@ワイルドカード-私は反対を尋ねることができました-なぜexですか?あなたの質問に答えるために:私は使ったex ことがないので、よく知りません。ところで、私edは存在していexたが存在しなかった(しかし反対ではない)セットアップを見てきました...最も注目すべきは私のラップトップです:)
don_crissti

いい答えです。:)私の答え:私はいつもVimを使っているので、exコマンドにはとても慣れています。viコロンで始まる入力可能なコマンドはすべてコマンドですex。もちろん、Vim固有の拡張機能はいくつかありますが、コアとなるコマンドのセットだけが信じられないほど強力で柔軟性があり、スクリプトによる編集には十分です。
ワイルドカード

私のマンジャロシステムにはexまだありませんed
半ば

8

GNU sedをインストールできない場合は、次を使用します。

sed "s/foo/fooofoo/g" abc.txt >abc.tmp && mv abc.tmp abc.txt

これはリダイレクトを使用して、sedの出力を一時ファイルに送信します。sedが正常に完了するabc.txtと、一時ファイルで上書きされます。

GNU sedのソースコードからわかるように、これはまさにそのとおりsed -iです。したがって、これはとほぼ同じくらい効率的sed -iです。

abc.tmp既に存在する可能性がある場合は、mktempまたは同様のユーティリティを使用して、一時ファイルの一意の名前を生成することができます。


手伝ってくれてありがとう。しかし、一時ファイルを作成せずに既存のファイルを更新できるオプションはありますか?
tpsaitwal 2016年

10
それを壊すのは嫌いですが、sedでさえ一時ファイルを作成します。git.savannah.gnu.org/cgit/sed.git/tree/sed/sed.c#n84
ジェフシャラー

1
ハードリンクを気にしない場合は、これを実行できます。私の例を参照してください。一時ファイルはまだ残っていますが、非表示(名前なし)です。一時edファイルがない場合は、ファイル全体をメモリに読み込むため、を使用する必要があります。
Toby Speight

3

と同等の機能が必要な場合はsed -i.bak、非常に簡単です。

GNU sed用の次のスクリプトについて考えてみます。

#!/bin/sh

# Create an input file to demonstrate
trap 'rm -r "$dir"' EXIT
dir=$(mktemp -d)
grep -v '[[:upper:][:punct:]]' /usr/share/dict/words | head >"$dir/foo"

# sed program - removes 'aardvark' and 'aardvarks'
script='/aard/d'

##########
# What we want to do
sed -i.bak -e "$script" "$dir"
##########

# Prove that it worked
ls "$dir"
cat "$dir/foo"

マークした行を次のように簡単に置き換えることができます

cp "$dir/foo" "$dir/foo.bak" && sed -e "$script" "$dir/foo.bak" >"$dir/foo"

これにより、既存のファイルがバックアップとして移動され、新しいファイルが書き込まれます。

同等のものが必要な場合

sed -i -e "$script" "$dir"  # no backup

その後、少し複雑になります。ファイルを開いて標準入力として読み込み、リンクを解除してから、sedの出力を置き換えて置き換えます。

( cp "$dir/foo" "$dir/foo.bak"; exec <"$dir/foo.bak"; rm "$dir/foo.bak"; exec sed -e "$script" >"$dir/foo" )

これはサブシェルで行うため、元のstdinはこの後も引き続き使用できます。入力を切り替えてサブシェルなしで元に戻すことは可能ですが、この方法は私にはより明確に思えます。

新しいfooファイルを作成するのではなく、最初に注意してコピーすることに注意してください。これは、ファイルが複数の名前で知られている(つまり、ハードリンクがある)場合、リンクを壊さないようにしたい場合に重要です。 。


3

まず、i\参照しているコマンドはテキスト行挿入するためのものであり、編集したテキストをファイルに保存するためのものはないことを知っておく必要があります。そのために使用するPOSIX指定の方法はありませんsed

できることはex、POSIX 指定されているuse です。

printf '%s\n' '%s/find/replace/g' 'x' | ex file.txt

xコマンドがあるため、「保存して終了。」使用することもできますwqx短いです。

%代替指令手段の開始時に看板は、「バッファ内のすべての行には、このコマンドを適用します。」あなたも使うことができます1,$s/find/replace/g


間の1つの主な違いexとはsedつまり、sedあるストリームエディタ。行ごとに順次動作するだけです。 exはそれよりもはるかに柔軟性が高く、実際にで直接インタラクティブなテキストファイル編集を行うことができますex。これはの前身viです。


1

目に見える一時ファイルを使用sedしていない:

別の表示可能な「一時ファイル」の作成を回避できます。

exec 3<abc.txt
rm abc.txt
sed 's/foo/fooofoo/' <&3 >abc.txt
exec 3<&-

説明

それがされるまでUnixライクなシステムは、実際にディスクからファイルの内容を削除しないでください、両方のファイルシステムにリンク解除、および任意のプロセスで開かれていません。そのexec 3<ため、ファイル記述子3 rm(ファイルシステムからリンクを解除するファイル)を読み取るためにシェルでファイルを開き、sedファイル記述子3を入力として呼び出します。

これはこれとは非常に異なることに注意してください。

# Does not work.
sed 's/foo/fooofoo/' <abc.txt >abc.txt

違いは、1つのコマンドで実行すると、シェルは同じファイルを読み取り用とファイルの切り捨てオプションを使用した書き込み用の両方に開くだけです。それでもファイルは同じなので、内容が失われます。ただし、読み取り用に開いてからrm書き込み用に同じパス名を開くと、実際には同じパス名で新しいファイルが作成されます(ただし、元のファイルがまだ開いているため、新しいiノードとディスクの場所に)。内容はまだ入手可能です。

その後、完了したら、以前に開いたファイル記述子を閉じることができます(これはexec 3<&-特別な構文で行われます)。これにより、元のファイルが解放され、オペレーティングシステムがそのディスク領域を削除(未使用としてマーク)できるようになります。

注意事項

このソリューションについては、いくつかの注意点があります。

  1. シェルはファイル記述子で「シーク」するポータブルな方法はないため、プログラムはコンテンツの一部を読み取ると、他のプログラムはファイルの残りの部分のみを参照します。そしてsed、ファイル全体を読み取ります。

  2. シェル/スクリプト/ sedが完了する前にkillされた場合、元のファイルが失われる可能性が少しあります。


明確にするために、@ TobySpeightはすでに彼の回答の最後にこのソリューションの例を投稿していますが、より詳細な詳細を使用できると思いました。
mtraceur 2016年

反対投票者へ:反対投票を辞めるだけで自分の気持ちが良くなると確信していますが、この回答でどのような問題があり、それをどのように改善できるかについてフィードバックを提供して、もっと貢献していただければ幸いです。 。
mtraceur

多分あなたはperl -iを使うことができます
c4f4t0r

@ c4f4t0r:返信が遅くなってすみません:はい、perl -i別の良いオプションです。質問は、特にSolarisのと互換性のある解決策を要求したsedとのソリューションとは対照的に、perlそしてawk、彼らが見つけすでに述べたもの。さらに、私の回答は主に、知っておくと便利で他の回答から欠落しているものを追加することを目的としています。
mtraceur 2016
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.