web-dev-qa-db-ja.com

grepおよびsedを使用して再帰的にすべてのファイルの文字列を検索および置換

私は得ています

sed: -e expression #1, char 22: unterminated `s' command 

スクリプトに問題がありますか?また、「oldstring」には特殊文字が含まれています

#!bin/bash
oldstring='<script>"[oldscript]"</script>'
newstring='<script>"[newscript]"</script>'
grep -rl $oldstring /path/to/folder | xargs sed -i s/$oldstring/$newstring/g
31
jmazaredo

@Didierが言ったように、区切り文字を/以外のものに変更できます:

grep -rl $oldstring /path/to/folder | xargs sed -i s@$oldstring@$newstring@g
42
wudeng
grep -rl $oldstring . | xargs sed -i "s/$oldstring/$newstring/g"
13
Sreedhar GS

GNU guysはgrepに再帰的なファイル検索を導入したときに本当に混乱しました。grepはファイル内のREを見つけ、一致する行(g/re/pを覚えていますか?)ファイルを見つけるための非常に明白な名前を持つ完全に優れたツールがあります。

とにかく、伝統的なUNIXのアプローチ(テストされていない)を使用して、あなたが望むことをする方法は次のとおりです。

find /path/to/folder -type f -print |
while IFS= read -r file
do
   awk -v old="$oldstring" -v new="$newstring" '
      BEGIN{ rlength = length(old) }
      rstart = index($0,old) { $0 = substr($0,rstart-1) new substr($0,rstart+rlength) }
      { print }
   ' "$file" > tmp &&
   mv tmp "$file"
done

Sedとgrepの代わりにawk/index()を使用することで、古い文字列または新しい文字列に表示される可能性があるすべてのREメタ文字をエスケープし、sed区切り文字として使用できる文字を把握する必要がなくなりますtは古い文字列または新しい文字列に表示されますが、置換は必要な文字列を含むファイルに対してのみ行われるため、grepを実行する必要はありません。ファイルの変更を行わずにファイルのタイムスタンプを変更したくない場合は、mvを実行する前にtmpと元のファイルの差分を作成するか、またはその前にfgrep -qをスローするだけです。ああ.

警告:上記は、改行を含むファイル名では機能しません。それらをお持ちの場合はお知らせください。それらの処理方法を説明します。

5
Ed Morton

sed式は引用符で囲む必要があります

sed -i "s/$oldstring/$newstring/g"
4
Steven Penny