Поиск без учета регистра и замена на sed - PullRequest
71 голосов
/ 10 декабря 2010

Я пытаюсь использовать 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 ]

63 голосов
/ 15 октября 2012

Чтобы быть понятным: On macOS - начиная с Mojave (10.14) - 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;'. Спасибо, Марк Рид

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

59 голосов
/ 10 декабря 2010

Примечание редактора : Это решение не работает на macOS (из коробки), поскольку оно применяется только к GNU sed, тогда как macOS поставляется с BSD sed.

С заглавной буквы "I".

sed 's/foo/bar/I' file
23 голосов
/ 06 ноября 2015

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

2 голосов
/ 28 августа 2018

FAQ sed посвящен тесно связанному без учета регистра поиску .Это указывает на то, что 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/
    
0 голосов
/ 20 января 2017

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

/pattern/s/xx/yy/g

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

/pattern/Is/xx/yy/g

Пример:

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

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

0 голосов
/ 19 января 2017

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

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

grep -i -l -r foo ./* 

this, чтобы исключить this_shell.sh (в случае, если вы поместили команду в скрипт с именем this_shell.sh ), передайте вывод в консоль, чтобы увидеть, что произошло, и затем используйте 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 позволяет просматривать только файлы с целевым текстом (что, вероятно, также может повысить производительность / скорость)

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

0 голосов
/ 23 июня 2016
sed 's/string1/string2/Ig'

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

0 голосов
/ 24 июня 2015

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

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