Поиск и замена без учета регистра на sed

Я пытаюсь использовать sed для извлечения текста из файла журнала.

Я могу сделать поиск и замену без особых проблем:

sed 's/foo/bar/' mylog.txt

тем не менее, я хочу сделать поиск нечувствительным к регистру. Из того, что я погуглил, это похоже на добавление i до конца команды должно работать:

sed 's/foo/bar/i' mylog.txt

однако это дает мне сообщение об ошибке:

sed: 1: "s/foo/bar/i": bad flag in substitute command: 'i'

что здесь не так, и как это исправить?

Я на macOS, в случае вопросы.

8 ответов


чтобы быть ясным: On macOS - по состоянию на Сьерра (10.12) -sed - это BSD реализация-не поддерживает сопоставление без учета регистраранее принятый ответ, который сам показывает GNU sed команда, получила этот статус из-за perl-решение уже упоминалось в комментариях.

чтобы сделать это решение на Perl работа с символы также, через UTF-8, используйте что-то вроде:

perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo"
  • -C включает поддержку UTF-8 для потоков и файлов, предполагая, что текущая локаль основана на UTF-8.
  • -Mutf8 говорит Perl интерпретировать исходный код как UTF-8 (в этом случае строка передается в -pe) - это более короткий эквивалент более многословным -e 'use utf8;'.спасибо, Марк Рид!--22-->

(обратите внимание, что используя awk также не является вариантом, as awk на macOS (т. е. BWK awk, a.к. a. BSD awk), похоже, совершенно не знает о местах вообще-его tolower() и toupper() функции игнорируют иностранные символы (и sub() / gsub() не имеют флагов нечувствительности к регистру для начала).)


заглавная буква "I".

sed 's/foo/bar/I' file

еще одна работа-вокруг sed на Mac OS X необходимо установить gsedиз MacPorts или HomeBrew, а затем создайте псевдоним sed='gsed'.


Mac-версия sed кажется немного ограниченным. Один из способов обойти это-использовать контейнер linux (через Docker), который имеет полезную версию sed:

cat your_file.txt | docker run -i busybox /bin/sed -r 's/[0-9]{4}/****/Ig'

на sed FAQ адресов, тесно связанных с учетом регистра поиск. Он указывает, что a) многие версии sed поддерживают флаг для него и b) это неудобно делать в sed, вы должны скорее использовать awk или Perl.

но чтобы сделать это в POSIX sed, они предлагают три варианта (адаптированные для замены здесь):

  1. преобразовать в верхний регистр и сохранить исходную строку в пространстве хранения; это не будет работать для подстановок, хотя, как исходный контент будет восстановлен перед печатью, поэтому он подходит только для вставки или добавления строк на основе совпадения без учета регистра.

  2. возможно, возможности ограничены FOO, Foo и foo. Они могут быть покрыты

    s/FOO/bar/;s/[Ff]oo/bar/
    
  3. для поиска всех возможных совпадений можно использовать скобочные выражения для каждого символа:

    s/[Ff][Oo][Oo]/bar/
    

у меня была аналогичная потребность, и я придумал это:

эта команда просто найти все файлы:

grep -i -l -r foo ./* 

этот исключить this_shell.sh (в случае, если вы поместите команду в скрипт под названиемthis_shell.sh), tee вывод на консоль, чтобы увидеть, что произошло, а затем использовать sed для каждого имени файла, найденного для замены текста foo на bar:

grep -i -l -r --exclude "this_shell.sh" foo ./* | tee  /dev/fd/2 | while read -r x; do sed -b -i 's/foo/bar/gi' "$x"; done 

Я выбрал этот метод, так как мне не понравилось, что все временные метки изменены для файлов не модифицированный. подача результата grep позволяет просматривать только файлы с целевым текстом (таким образом, вероятно, может улучшить производительность / скорость)

перед использованием обязательно создайте резервную копию файлов и протестируйте их. Может не работать в некоторых средах для файлов со встроенными помещениями. (?)


если вы делаете сопоставление шаблонов сначала, например,

/pattern/s/xx/yy/g

тогда вы хотите поставить I модель:

/pattern/Is/xx/yy/g

пример:

echo Fred | sed '/fred/Is//willma/g'

возвращает willma, без I, он возвращает строку нетронутой (Fred).


sed 's/string1/string2/Ig'

капитал I - это опция, которая полезна для поиска строки независимо от чувствительности к регистру.