web-dev-qa-db-ja.com

MacおよびLinuxのテキストファイルでの再帰的な検索と置換

Linuxシェルでは、次のコマンドが再帰的に検索して、「this」のすべてのインスタンスを「that」に置き換えます(目の前にLinuxシェルはありませんが、実行する必要があります)。

find . -name "*.txt" -print | xargs sed -i 's/this/that/g'

OSXの同様のコマンドはどのようになりますか?

111
Jack

OS XはBSDとGNUツールを組み合わせて使用​​するため、常にドキュメントを確認することをお勧めします(ただし、lessはOS Xのマンページにも適合していません)。

https://developer.Apple.com/legacy/library/documentation/Darwin/Reference/ManPages/man1/sed.1.html

sedは、バックアップの拡張子として-iの後に引数を取ります。バックアップなしの空の文字列(-i '')を指定します。

次のようにする必要があります。

LC_ALL=C find . -type f -name '*.txt' -exec sed -i '' s/this/that/ {} +

-type fは良い方法です。 sedは、ディレクトリなどを指定すると文句を言います。 -execxargsよりも優先されます。 -print0などを気にする必要はありません。末尾の{} +は、findがすべての結果を引数として、結果ごとに再実行するのではなく、呼び出されたコマンドの1つのインスタンスに追加することを意味します。 (1つの例外は、OSで許可されているコマンドライン引数の最大数に違反した場合です。その場合、findは複数のインスタンスを実行します。)

221
TaylanUB

Macの場合、より類似したアプローチは次のようになります。

find . -name '*.txt' -print0 | xargs -0 sed -i "" "s/form/forms/g"
119
Will

Mac OSX 10.11.5では、これは正常に機能します。

grep -rli 'old-Word' * | xargs -I@ sed -i '' 's/old-Word/new-Word/g' @
12
madx

代替ソリューションとして、Mac OSX 10.7.5でこれを使用しています

grep -ilr 'old-Word' * | xargs -I@ sed -i '' 's/old-Word/new-Word/g' @

クレジットは次のとおりです: Todd Cesereの答え

11
Maciej Gurban

上記のいずれもOSXでは機能しません。

以下をせよ:

Perl -pi -w -e 's/SEARCH_FOR/REPLACE_WITH/g;' *.txt
10
eb80

LinuxとMac OS Xの両方で動作するバージョン(-eスイッチをsedに追加することにより):

export LC_CTYPE=C LANG=C
find . -name '*.txt' -print0 | xargs -0 sed -i -e 's/this/that/g'
7
vroc

これは私の実行可能なものです。 Mac OS X 10.10.4の場合

grep -e 'this' -rl . | xargs sed -i '' 's/this/that/g'

上記のものはfindを使用し、検索テキストを含まないファイルを変更します(ファイルの最後に新しい行を追加します)。これは冗長です。

1
NoteCode

Zshターミナルを使用している場合、ワイルドカードマジックを使用できます。

sed -i "" "s/search/high-replace/g" *.txt

1
Mentor
find . -type f | xargs sed -i '' 's/string1/string2/g'

詳細については here を参照してください。

0
user2725109

https://bitbucket.org/masonicboom/serp は、特定のディレクトリ内のファイル内のテキストを再帰的に検索および置換するOSXでテストされたgoユーティリティ(クロスプラットフォームなど)です。各交換を確認します。それは新しいので、バグがあるかもしれません。

使用法は次のようになります。

$ ls test
a  d  d2 z
$ cat test/z
hi
$ ./serp --root test --search hi --replace bye --pattern "*"                         
test/z: replace hi with bye? (y/[n]) y
$ cat test/z
bye
0
user4425237

このコマンドを入力するたびに、私はいつもそれを使い果たしているか、フラグを忘れているようです。 TaylanUBの回答に基づいてGitHubでGistを作成しました。これは、現在のディレクトリからグローバル検索置換を実行します。これはMac OSX固有です。

https://Gist.github.com/nateflink/9056302

ターミナルを開いてコピーするだけなので、いいですね。

curl -s https://Gist.github.com/nateflink/9056302/raw/findreplaceosx.sh | bash -s "find-a-url.com" "replace-a-url.com"

奇妙なバイトシーケンスエラーが発生する可能性があるため、完全なコードを次に示します。

#!/bin/bash
#By Nate Flink

#Invoke on the terminal like this
#curl -s https://Gist.github.com/nateflink/9056302/raw/findreplaceosx.sh | bash -s "find-a-url.com" "replace-a-url.com"

if [ -z "$1" ] || [ -z "$2" ]; then
  echo "Usage: ./$0 [find string] [replace string]"
  exit 1
fi

FIND=$1
REPLACE=$2

#needed for byte sequence error in ascii to utf conversion on OSX
export LC_CTYPE=C;
export LANG=C;

#sed -i "" is needed by the osx version of sed (instead of sed -i)
find . -type f -exec sed -i "" "s|${FIND}|${REPLACE}|g" {} +
exit 0
0
Nate Flink

私はこのフォーマットを使用しましたが......非常に奇妙だとわかったすべてのインスタンスを実際に変更するには、3回以上実行する必要がありました。一度実行すると、すべてではなく各ファイルの一部が変更されます。まったく同じ文字列を2〜4回実行すると、すべてのインスタンスがキャッチされます。

find . -type f -name '*.txt' -exec sed -i '' s/thistext/newtext/ {} +
0
user1399145