По умолчаниюsed
используются базовые регулярные выражения POSIX , которые не содержат |
оператора чередования. Многие версии sed
, в том числе GNU и FreeBSD, поддерживают переключение на расширенные регулярные выражения , которые включают |
чередование. То, как вы это делаете, варьируется: GNU sed использует-r
, в то время как FreeBSD , NetBSD , OpenBSD и OS X sed используют -E
. Другие версии в основном не поддерживают его вообще. Вы можете использовать:
echo 'cat dog pear banana cat dog' | sed -E -e 's/cat|dog/Bear/g'
и он будет работать на этих системах BSD и sed -r
с GNU.
sed
Похоже, что GNU имеет полностью недокументированную, но рабочую поддержку -E
, поэтому, если у вас есть многоплатформенный скрипт, ограниченный вышеприведенным, это ваш лучший вариант. Так как это не задокументировано, вы, вероятно, не можете на него положиться.
В комментарии отмечается, что версии BSD также поддерживаются -r
как недокументированный псевдоним. OS X до сих пор не работает, и старые машины NetBSD и OpenBSD, к которым у меня есть доступ, тоже нет, но есть и NetBSD 6.1. Коммерческие Unices, которых я могу достичь повсеместно, не имеют. Таким образом, несмотря на все это, вопрос переносимости становится довольно сложным в данный момент, но простой ответ - переключиться на,awk
если вам это нужно, который использует ERE повсюду.
-r
вариант как синоним-E
для совместимости с GNU СЭД. OpenBSD и OS Xsed -E
будут интерпретировать экранированный канал как буквальный канал, а не как оператор чередования. Вот рабочая ссылка на справочную страницу NetBSD, а вот для OpenBSD, которой нет десяти лет.-E
: developer.apple.com/library/mac/documentation/Darwin/Reference/…-E
gnu.org/software/sed/manual/sed.html#index-_002dE .Это происходит потому, что
(a|b)
это расширенное регулярное выражение, а не простое регулярное выражение. Используйте-E
опцию, чтобы справиться с этим.Со
sed
страницы руководства :Обратите внимание, что
-r
это еще один флаг для той же вещи, но-E
он более переносим и будет даже в следующей версии спецификаций POSIX.источник
Портативный способ сделать это - и более эффективный способ - с помощью адресов. Ты можешь это сделать:
Таким образом, если строка не содержит строку cat и не содержит строку dog
sed
b
, вышедшую из сценария, она автоматически печатает свою текущую строку и вытягивает следующую, чтобы начать следующий цикл. Поэтому он не выполняет следующую инструкцию - которая в этом примереc
обрабатывает всю строку, чтобы прочитать Bear, но он может сделать что угодно.Вероятно, стоит также отметить, что любой оператор, следующий за
!b
этойsed
командой, может совпадать только в строке, содержащей либо строку,dog
либоcat
- так что вы можете выполнять дополнительные тесты без какой-либо опасности совпадения со строкой, которая не соответствует - что означает, что теперь вы можете применять правила только один или другой, а также.Но это дальше. Вот вывод этой команды:
Вы также можете переносить таблицу поиска с обратными ссылками.
В этом простом примере можно настроить гораздо больше, но
sed
в долгосрочной перспективе это может привести к гораздо более гибким сценариям.В первой строке I е
x
изменение трюм и шаблон затем вставить строку<space>
кошки<space>
собаки<space>
в трюм до еx
меняющихся их обратно.С этого момента и в каждой следующей строке я
G
и удерживаю пробел, добавленный к пробелу, затем проверяю, соответствуют ли все символы от начала строки до новой строки, которую я только что добавил в конце, строке, окруженной пробелами после нее. Если это так, я заменяю весь лот на Bear, а если нет, то это не причинит вреда, потому что я в следующий разP
набираю только до первой встречающейся новой строки в пространстве образца, затемd
удаляю все это.И когда я говорю гибкий, я имею в виду это. Здесь он заменяет кошку на BrownBear и собаку на BlackBear :
Конечно, вы можете значительно расширить содержание таблицы поиска - я взял идею из писем Грег Уббена по этому вопросу, когда в 90-х он описал, как он построил грубый калькулятор из одного
sed s///
утверждения.источник
это довольно старый вопрос, но на тот случай, если кто-то захочет попробовать, есть довольно простой способ сделать это в sed с помощью sed-файлов. Каждый параметр может быть указан в отдельной строке, и sed оценит каждый из них. Это логический эквивалент или. Например, чтобы удалить строки, содержащие определенный код:
ты можешь сказать :
sed -E '/^\/\*!(40103|40101|40111).*\/;$/d'
или поместите это в свой файл sed:
источник
Вот методика, которая не использует какие-либо специфические для реализации опции
sed
(например-E
,-r
). Вместо описания шаблона как одного регулярного выраженияcat|dog
, мы можем просто запуститьsed
дважды:Это очевидный обходной путь, но стоит поделиться. Естественно, это обобщает более чем две строки шаблона, хотя очень длинная цепочка
sed
не слишком хорошо выглядит.Я часто использую
sed -i
(что работает одинаково во всех реализациях) для внесения изменений в файлы. Здесь может быть красиво включен длинный список строк шаблона, поскольку каждый временный результат сохраняется в файл:источник