26

sed に渡されたファイルが正常に変更されたかどうかを判断する賢い方法を見つけようとしています。

基本的に、ファイルの変更日を見なくても、ファイルが変更されたかどうかを知りたいです。

これが必要な理由は、sed がパターンを正常に置き換えた場合に、追加の作業を行う必要があるためです。

私は現在持っています:

    grep -q $pattern $filename
    if [ $? -eq 0 ]
    then
        sed -i s:$pattern:$new_pattern: $filename
                # DO SOME OTHER STUFF HERE
    else
        # DO SOME OTHER STUFF HERE
    fi

上記のコードは少し高価なので、ここでいくつかのハックを使用できるようにしたいと思います.

4

10 に答える 10

37

パーティーには少し遅れましたが、他の人の利益のために、「w」フラグがまさに私が探していたものであることがわかりました。

sed -i "s/$pattern/$new_pattern/w changelog.txt" "$filename"
if [ -s changelog.txt ]; then
    # CHANGES MADE, DO SOME STUFF HERE
else
    # NO CHANGES MADE, DO SOME OTHER STUFF HERE
fi

changelog.txtそれぞれの変更 (つまり、変更されたテキスト) がそれぞれの行に含まれます。変更がなかった場合は、changelog.txt0 バイトになります。

本当に役立つ sed リソース (およびこの情報を見つけた場所) はhttp://www.grymoire.com/Unix/Sed.htmlです。

于 2015-03-10T14:42:47.173 に答える
10

これらのGNUSed拡張機能が役立つと思うかもしれません

t label

If a s/// has done a successful substitution since the last input line
was read and since the last t or T command, then branch to label; if
label is omitted, branch to end of script.

q [exit-code]

Immediately quit the sed script without processing any more input, except 
that if auto-print is not disabled the current pattern space will be printed. 
The exit code argument is a GNU extension.

まさにあなたが探しているもののようです。

于 2012-08-27T15:25:57.040 に答える
10

これはうまくいくかもしれません(GNU sed):

sed -i.bak '/'"$old_pattern"'/{s//'"$new_pattern"'/;h};${x;/./{x;q1};x}' file || echo changed

説明:

  • /'"$old_pattern"'/{s//'"$new_pattern"'/;h}パターン スペース (PS) に が含まれている場合はold pattern、 に置き換えてnew pattern、PS をホールド スペース (HS) にコピーします。
  • ${x;/./{x;q1};x}最後の行に遭遇したら、HS にスワップし、文字列が存在するかどうかをテストします。HS で文字列が見つかった場合 (つまり、置換が行われた場合) は、元の PS にスワップ バックし、終了コード を使用して終了します1。それ以外の場合は、元の PS にスワップ バックし、終了コード0(デフォルト) で終了します。
于 2012-08-27T16:24:41.023 に答える
5

代わりに使用できますawk

awk '$0 ~ p { gsub(p, r); t=1} 1 END{ exit (!t) }' p="$pattern" r="$repl"

私はこの-i機能を無視しています。必要に応じてシェルを使用してリダイレクトを行うことができます。

はぁ。シェルの基本的なチュートリアルを求める以下の多くのコメント。上記のコマンドは次のように使用できます。

if awk '$0 ~ p { gsub(p, r); t=1} 1 END{ exit (!t) }' \
        p="$pattern" r="$repl" "$filename" > "${filename}.new"; then
    cat "${filename}.new" > "${filename}"
    # DO SOME OTHER STUFF HERE
else
    # DO SOME OTHER STUFF HERE
fi

「DO SOME OTHER STUFF HERE」がそれぞれの場合で同じかどうかはわかりません。2 つのブロック内の同様のコードは、それに応じてリファクタリングする必要があります。

于 2012-08-27T14:49:36.850 に答える
5

元のファイルと sed 出力を比較して、変更されたかどうかを確認できます。

sed -i.bak s:$pattern:$new_pattern: "$filename"
if ! diff "$filename" "$filename.bak" &> /dev/null; then
  echo "changed"
else
  echo "not changed"
fi
rm "$filename.bak"
于 2012-08-27T14:49:50.980 に答える
0

それは古い質問であり、sed の代わりに awk を使用することがおそらく最良のアイデアであることはわかっていますが、sed を使い続けたい場合は、-w フラグを使用することをお勧めします。w フラグの file 引数には、一致する行のみが含まれます。したがって、空でないことを確認するだけで済みます。

于 2016-03-06T08:00:59.087 に答える