2013-04-12 12 views
33

実行時にjson設定ファイルを更新するのにsedを使用しています。パターンはJSONファイルで一致し、リターンコードとまだsed終了0sedのリターンコードが一致しない

が0に戻ると正常に完了したことを意味するが、それは適切なパターンを検索し、ファイルを更新doesntの場合、なぜsed戻り0を実行していない時々 、 ?そのための回避策はありますか?

ありがとうございます!

+6

はい、「sed」に関しては、それはその仕事をしていました。ファイルを編集しようとしました。ファイルが読み込み不可能な場合など、エラーコードが返されます。要するに、「sed」はパターンがファイルに出現するかどうかを決める*ための最良のツールではないと私は思います。 – cnicutar

+0

@cnicutar多くの人が答えとしてコメントを投稿していますが、コメントエリアに答えを入れるだけと思います。 OPはパターンマッチをチェックしたいと思うだけでなく、パターンマッチなら../pat/s/foo/bar/...のように何かしたいと思っています。 – Kent

+0

@Kentそれで私は回答。私はなぜ 'sed'がこれをしているのかを説明しましたが、受け入れられる解決策を思いつくことができませんでした。私が考えることができるすべては、ファイルが一致するかどうかを判断するために、 'sed'の前に別のコマンドを呼び出す必要がありました。理想的には、あるコマンドでこれを行うことができる解決策(おそらく 'awk'と' gsub')が必要です。 – cnicutar

答えて

31

@cnicutarとしてコメントされました。コマンドの戻りコードは、コマンドが正常に実行されたことを意味します。コード/スクリプトで実装したロジックとは関係ありません。

お持ちの場合はそう:

echo "foo"|sed '/bar/ s/a/b/' 
sedの

sedは、0を返しますが、あなたには、いくつかの構文/発現書き込みエラー、または入力/ファイルが存在しない、sedの場合は、あなたの要求を実行することはできませんが1を返します。 。

回避策

これは実際に回避策ではありません。 (manページから):ここにあなたが望むとおりに終了コードを定義することができ

q [exit-code] 

SEDがqコマンドがあります。例えば:

マッチした場合:

kent$ echo "foo"|sed '/foo/ {s/f/b/;q}'           
boo 

kent$ echo $? 
0 

比類のない場合:

kent$ echo "trash"|sed '/foo/{s/f/b/;q}; /foo/!{q100}' 
trash 

kent$ echo $? 
100 

私は、これは、あなたの質問に答える願っています。

編集

私はそれを追加する必要があり、上記の例では、ちょうど1ライン処理のためです。私はあなたの正確な要件を知らない。あなたがexit 1を取得したいとき。 1行不一致またはファイル全体。ファイル全体がケースを不一致ならば、あなたはAWKを検討し、あるいはあなたのテキスト処理の前にgrepを行うことができます...

+0

純粋なawesomeness。私は 'q'を見ていたが、それをやる方法は知らなかった。 – cnicutar

+0

素晴らしい!これは私のために働くだろう。どうもありがとう! – bram

+2

この答えはGNU sedには最適ですが、 'q'オプションはBSD(Mac)sedに移植できないことに注意してください。 – spinup

38

これは(GNU SED)あなたのために働くかもしれない:

sed '/search-string/{s//replacement-string/;h};${x;/./{x;q0};x;q1}' file 

search-stringは、それを発見された場合replacement-stringに置き換えられ、ファイルの最後にsedは、0リターンコードで終了します。置換が行われない場合、戻りコードは1になります。

より詳細な説明:現在の行がロードされているパターンスペース(PS)(マイナス改行)とスペアレジスタのホールドと呼ばれる:sedのユーザーで

は2個の彼の処分でレジスタがありスペース(HS)は最初は空です。

一般的な考え方は、置換が行われたかどうかを示すフラグとしてHSを使用することです。ファイルの最後にHSがまだ空の場合、変更は行われていません。それ以外の場合は変更が発生しています。

コマンド/search-string/試合PSであり、それは、次の中括弧の間search-stringコマンドを含んでいることが分かっている場合に実行されているものは何でもしてsearch-string

まず置換s//replacement-string/(左側側が空の場合はsedのは、search-stringすなわち最後の正規表現を使用するため、s//replacement-strings/search-string/replacement-string/と同じである)、この次hコマンドは、PSのコピーを作成し、それを置きますHS。

sedコマンド$は、ファイルの最後の行を認識するために使用され、次のようになります。

最初にxコマンドが2つのレジスタをスワップするため、HSはPSになり、PSはHSになります。

次に、PSは任意の文字が検索されます。/./.は任意の文字に一致します)HS(今はPS)は、置換が行われるまで最初は空だったことを覚えています。条件が真であれば、xが再び実行され、q0コマンドがすべてのsed処理を終了し、戻りコードを0に設定します。そうでない場合はxコマンドが実行され、戻りコードは1に設定されます。

N.B. qはsed処理を終了しますが、sedによってPSが再アセンブルされ、通常通りに印刷されることはありません。

別の方法:

sed '/search-string/!ba;s//replacement-string/;h;:a;$!b;p;x;/./Q;Q1' file 

か:

sed '/search-string/,${s//replacement-string/;b};$q1' file 
+0

あなたの提案をありがとう。 – bram

+1

+1ケントの例がうまく動作しなくなってしまった。私はまたあなたの最後のものを試して、それを働かせることができませんでした。私はそれが私が使用している検索文字列と関係があると確信しています。しかし、あなたのスレッドの最初のものは素晴らしいです! –

+1

'$' :-)に 'q'を入れた場合+1 – anishsane

0

私は、一致が見つかった時に終了して、ファイルを切り捨てる(と一致する行を除外)したいと考えていました。これは、ファイルの最後に行を追加するプロセスが再実行される場合に便利です。 "Q; Q1"は機能しませんでしたが、次のように単純に "Q1"が実行されました:

if sed -i '/ text検索するには/ Q1' file.txt ファイルの最後に空白行を挿入してください+新しい行 fi 新しい行だけを空白行なしで挿入する

10

これらの答えはすべてあまりにも複雑です。 grepを使って、置き換えたいものがsedを使って置き換えているかどうかを調べるためのシェルスクリプトを書きます。以下は

grep -q $TARGET_STRING $file 
if [ $? -eq 0 ] 
then 
    echo "$file contains the old site" 
    sed -e "s|${TARGET_STRING}|${NEW_STRING}|g" .... 
fi 
+2

'$ file'が'/dev/stdin'の場合は動作しません。 – Elena

+1

これはCygwinを使わないWindowsでもうまくいきません;-) – Cameron

+0

これはもっと長くても間違いなく読みやすくなりました。ありがとう! –

1

我々はsed -rnまたはsed -rで使用したパターンです。

検索と置換コマンド(「s/.../.../...」)全体はオプションです。 searchとreplaceを使用すると、スピードと$ matchReにすでに一致しているので、できるだけ速く$ searchRe値を使用します。文字の再検証は必要ありません。{$ len}はパターンの固定長セクションです。

noneの戻り値は$ notFoundExitです。以下の理由から

/$matchRe/{s/$searchRe/$replacement/$options; Q}; q$notFoundExit 

  • マッチと比類のないケース
  • 両方のための時間がない無駄なテストはありません、余分な枝
  • またはバッファ
  • から合理的な柔軟性をコピーする無駄な時間がありません

Qコマンドの大文字と小文字を区別すると、終了がいつ発生するかによって動作が異なります。ブール論理を複数のライン入力に適用する動作には、ソリューションがより複雑になります。

0

すでにわかっているように、sedが一致しなかった場合、入力文字列を返します。エラーは発生していません。入力文字列と出力文字列の違いは一致を意味しますが、一致しても文字列に違いはありません。すべてのsedが単純にすべての入力文字にマッチした可能性があります。 欠陥は、以下の例で作成されg=abc1 2を与える設定中g=Xabc1は、1を与える

h=$(echo "$g" | sed 's/.*\(abc[[:digit:]]\).*/\1/g')  
if [ ! "$h" = "$g" ]; then  
    echo "1" 
else  
    echo "2"  
fi 

。これらの入力文字列は両方ともsedとマッチします!したがって、sedが一致しているかどうかを判断することは難しいかもしれません。解決策:

この場合、sedが一致した場合には1が出力されます。

関連する問題