Рекурсивный поиск и замена в текстовых файлах на Mac и Linux

В оболочке linux следующая команда будет рекурсивно искать и заменять все экземпляры 'this' на "это" (у меня нет оболочки Linux передо мной, но она должна делать).

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

Как будет выглядеть аналогичная команда в OSX?

Ответ 1

OS X использует сочетание инструментов BSD и GNU, поэтому лучше всегда проверять документацию (хотя у меня было такое, что даже less не соответствовало man-странице 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 - просто хорошая практика; Сед будет жаловаться, если вы дадите ему каталог или около того. -exec предпочтительнее xargs; вам не нужно беспокоиться о -print0 или о чем-то еще. {} + В конце означает, что команда find будет добавлять все результаты в качестве аргументов к одному экземпляру вызываемой команды вместо повторного запуска для каждого результата. (Единственное исключение - это когда максимальное количество аргументов командной строки, разрешенных ОС, нарушается; в этом случае find запускает более одного экземпляра.)

Ответ 2

Для mac, более похожий подход будет таким:

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

Ответ 3

Как альтернативное решение, я использую этот вариант на Mac OSX 10.7.5

grep -ilr 'old-word' * | xargs [email protected] sed -i '' 's/old-word/new-word/g' @

Кредит идет: Ответ Тодда Цезер

Ответ 4

В Mac OSX 10.11.5 это отлично работает:

grep -rli 'old-word' * | xargs [email protected] sed -i '' 's/old-word/new-word/g' @

Ответ 5

Ничего из вышеперечисленного не работает в OSX.

Выполните следующие действия:

perl -pi -w -e 's/SEARCH_FOR/REPLACE_WITH/g;' *.txt

Ответ 6

Версия, которая работает как на 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

Это моя работоспособная. на Mac OS X 10.10.4

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

Вышеупомянутые приложения find изменят файлы, которые не содержат текст поиска (добавьте новую строку в конец файла), который является подробным.

Ответ 8

Если вы используете zsh-терминал, вы можете использовать магию подстановочных знаков:

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

Ответ 9

Всякий раз, когда я набираю эту команду, мне всегда кажется, что она ее подвешивает или забывает флаг. Я создал Gist на github, основанный на ответе TaylanUB, который заменяет глобальную находку из текущего каталога. Это специфический 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

Ответ 10

https://bitbucket.org/masonicboom/serp - это утилита go (т.е. кросс-платформенная), протестированная на OSX, которая выполняет рекурсивный поиск и замену текста в файлах внутри данного каталога и подтверждает каждую замену. Это новое, поэтому может быть ошибкой.

Использование выглядит следующим образом:

$ 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

Ответ 11

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

Обратитесь сюда для получения дополнительной информации.

Ответ 12

Я использовал этот формат - но... я обнаружил, что мне нужно было запустить его три или более раз, чтобы заставить его фактически изменять каждый экземпляр, что мне показалось очень странным. Запуск его один раз изменит некоторые в каждом файле, но не во всех. Выполнение одной и той же строки два-четыре раза перехватит все экземпляры.

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

Ответ 13

Команда OSX должна быть точно такой же, как и Unix под симпатичным интерфейсом.

Ответ 14

может просто сказать $PWD вместо "."