Поиск без учета регистра и замена на 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'
Что здесь происходит, и как мне это исправить?
Ответы
Ответ 1
Для ясности: в macOS - с Mojave (10.14) - sed
- которая является реализацией BSD - НЕ поддерживается сопоставление без учета регистра - трудно поверить, но это правда, ранее принятый ответ, который сам показывает команду GNU sed
, получил этот статус из-за решения perl
-based, упомянутого в комментариях.
Чтобы это решение Perl работало и с иностранными символами, через UTF-8 используйте что-то вроде:
perl -C -Mutf8 -pe 's/öœ/oo/i' <<< "FÖŒ" # -> "Foo"
-C
включает поддержку UTF-8 для потоков и файлов при условии, что текущим языковым стандартом является UTF-8 -based.
-Mutf8
говорит Perl интерпретировать исходный код как UTF-8 (в данном случае строка, переданная в -pe
) - это более короткий эквивалент более подробного -e 'use utf8;'.
Thanks, Mark Reed
(Обратите внимание, что с помощью awk
тоже не вариант, так как awk
в macOS (то есть BWK awk, он же BSD awk), похоже, совершенно не знает о локалях - его tolower()
и [ Функции TG411] игнорируют посторонние символы (а у sub()
/gsub()
нет флагов нечувствительности к регистру для начала).)
Ответ 2
Editor note: This solution does not work on macOS (out of the box), because it only applies to GNU [TG40], whereas macOS comes with BSD [TG41].
Прописать "я".
sed 's/foo/bar/I' file
Ответ 3
Еще одна задача для sed
в Mac OS X - установить gsed
из MacPorts или HomeBrew, а затем создать псевдоним sed='gsed'
.
Ответ 4
Mac версия sed
кажется немного ограниченной. Один из способов обойти это - использовать контейнер linux (через Docker), который имеет полезную версию sed
:
cat your_file.txt | docker run -i busybox /bin/sed -r 's/[0-9]{4}/****/Ig'
Ответ 5
sed FAQ относится к тесно связанному поиску без учета регистра. Это указывает на то, что a) многие версии sed поддерживают для него флаг и b) это неудобно делать в sed, лучше использовать awk или Perl.
Но чтобы сделать это в POSIX sed, они предлагают три варианта (адаптированных для замены здесь):
Преобразовать в верхний регистр и сохранить оригинальную строку в удерживающем пространстве однако это не сработает для подстановок, поскольку исходное содержимое будет восстановлено перед печатью, поэтому оно подходит только для вставки или добавления строк на основе нечувствительного к регистру соответствия.
Возможно, возможности ограничены FOO
, Foo
и foo
. Они могут быть покрыты
s/FOO/bar/;s/[Ff]oo/bar/
Для поиска всех возможных совпадений можно использовать скобочные выражения для каждого символа:
s/[Ff][Oo][Oo]/bar/
Ответ 6
У меня была аналогичная потребность, и я придумал следующее:
эту команду, чтобы просто найти все файлы:
grep -i -l -r foo ./*
этот, чтобы исключить this_shell.sh(в случае, если вы поместите команду в script, называемой this_shell.sh), введите результат в консоль, чтобы узнать, что произошло, а затем используйте sed для каждого имени файла, найденного для замены текст foo с полосой:
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 позволяет просматривать только файлы с целевым текстом (таким образом, вероятно, это может повысить производительность и скорость)
Обязательно создавайте резервные копии файлов и проверяйте их перед использованием. Может не работать в некоторых средах для файлов со встроенными пространствами. (?)
Ответ 7
Если вы делаете сопоставление с шаблоном первым, например,
/pattern/s/xx/yy/g
Затем вы хотите поставить I
после шаблона:
/pattern/Is/xx/yy/g
Пример:
echo Fred | sed '/fred/Is//willma/g'
возвращает willma
; без I
возвращает строку без изменений (Fred
).
Ответ 8
sed 's/string1/string2/Ig'
Capital I
- это опция, которая полезна для поиска строки независимо от чувствительности к регистру.