AIX で sed -i を使用した find コマンドの再構築

AIX で sed -i を使用した find コマンドの再構築

文字列を検索してsedコマンドで置き換えるスクリプトがあります。文字列に特殊文字が含まれている場合、スクリプトは特殊文字をエスケープします(スラッシュは除外されます。スラッシュは現在のsed区切り文字であり、列はbash行の文字列を表示するため)。

問題は次のとおりです。

raw_searchstring='SearchForThis';
raw_replacementstring='ReplaceWithThis';

#Escape special characters:
quoted_searchstring=$(printf %s "$raw_searchstring" | sed 's/[][()\.^$?*+]/\\&/g');
quoted_replacementstring=$(printf %s "$raw_replacementstring" | sed 's/[][()\.^$?*+]/\\&/g');

find ./ -type f -exec sed -i -r "s/$quoted_searchstring/$quoted_replacementstring/" {} \;

Ubuntuでこれをテストしましたが、うまくいきます。

ただし、AIXシステムではスクリプトを実行する必要があります。 sed -iを使用したインライン編集をサポートしていないため、ここで同様の質問で提案されているように、次のことを試しました(AIX用sed - 内部編集):

find ./ -type f -exec sed -r 's/$quoted_searchstring/$quoted_replacementstring/' infile > tmp.$$ && mv tmp.$$ infile {} \;

ここでエラーが発生します。

find: missing argument to `-exec'

findだから私は次の行を使っていくつかの-execステートメントを渡しました。

find /home/tobias/Desktop -type f -exec sed -r 's/$quoted_searchstring/$quoted_replacementstring/' infile > tmp.$$ {} \; -exec mv tmp.$$ infile {} \;

これも機能しません。

sed: can't read infile: No such file or directory

何が間違っているのかわかりません。このコード行を編集したり、正しい方向を教えてもらえますか?

答え1

実行されたコマンドと同じシェル演算子を使用しようとしたため、試行は機能しませんが、&&これらの演算子をコマンドに直接入力して呼び出しシェルで実行します。あなたのコマンドは次のように解析されます。>findfind

find … > tmp.$$ && mv …

たとえば、最初のfind呼び出しは次のようになります。

find ./ -type f -exec sed 's/$quoted_searchstring/$quoted_replacementstring/' infile

出力はにリダイレクトされますtmp.$$。このコマンドには他の問題があります。 (infileこれは{}見つかったファイルです。find)sed式の周囲の一重引用符はシェル変数を使用しているため、二重引用符でなければなりません。

実行されたコマンドにシェル設定を使用する必要があるため、実行シェルにfind連絡してください。find

find … -exec sh -c '…' {} \;

引用の問題を回避するには、引用符で引用符で入力する必要がある項目(sed式など)を引数として渡しますsh

find ./ -type f -exec sh -c '
    sed "$0" "$1" >"$1.new" && mv "$1.new" "$1"
  ' "s/$quoted_searchstring/$quoted_replacementstring/" {} \;

少し読みやすく、パフォーマンスを向上させるためにフォーム-exec … {} +とシェルループを使用できます。

find ./ -type f -exec sh -c '
    for x; do
      sed "$0" "$x" >"$x.new" && mv "$x.new" "$x";
    done
  ' "s/$quoted_searchstring/$quoted_replacementstring/" {} +

あるいは、AIXバージョンがksh93古すぎない場合は、再帰ワイルドカード機能(ksh93pで導入)を使用することもできます。

set -G
for x in **; do
  [[ -f $x ]] || continue
  sed "s/$quoted_searchstring/$quoted_replacementstring/" "$x" >"$x.new" && mv "$x.new" "$x";
done

-rとにかくEREを使用するためのフラグはGNU拡張であるため、デフォルトの正規表現を生成するには文字列 - 正規表現変換も調整する必要があります。また、既存のコードにはいくつかのバグがあります。私はスラッシュを引用するのを忘れ、代替テキストから正しい文字を引用しませんでした。

quoted_searchstring=$(printf %s "$raw_searchstring" | sed 's![[\/.^$*]!\\&!g');
quoted_replacementstring=$(printf %s "$raw_replacementstring" | sed -e 's![][\/&]!\\&!g' -e '!$ s!$!\\!');

関連情報