Портативный способ сделать это - и более эффективный способ - с помощью адресов. Ты можешь это сделать:
printf %s\\n cat dog pear banana cat dog |
sed -e '/cat/!{/dog/!b' -e '};cBear'
Таким образом, если строка не содержит строку cat и не содержит строку dog sed
b
, вышедшую из сценария, она автоматически печатает свою текущую строку и вытягивает следующую, чтобы начать следующий цикл. Поэтому он не выполняет следующую инструкцию - которая в этом примере c
обрабатывает всю строку, чтобы прочитать Bear, но он может сделать что угодно.
Вероятно, стоит также отметить, что любой оператор, следующий за !b
этой sed
командой, может совпадать только в строке, содержащей либо строку, dog
либо cat
- так что вы можете выполнять дополнительные тесты без какой-либо опасности совпадения со строкой, которая не соответствует - что означает, что теперь вы можете применять правила только один или другой, а также.
Но это дальше. Вот вывод этой команды:
###OUTPUT###
Bear
Bear
pear
banana
Bear
Bear
Вы также можете переносить таблицу поиска с обратными ссылками.
printf %s\\n cat dog pear banana cat dog |
sed '1{x;s/^/ cat dog /;x
};G;s/^\(.*\)\n.* \1 .*/Bear/;P;d'
В этом простом примере можно настроить гораздо больше, но sed
в долгосрочной перспективе это может привести к гораздо более гибким сценариям.
В первой строке I е x
изменение трюм и шаблон затем вставить строку <space>
кошки <space>
собаки<space>
в трюм до е x
меняющихся их обратно.
С этого момента и в каждой следующей строке я G
и удерживаю пробел, добавленный к пробелу, затем проверяю, соответствуют ли все символы от начала строки до новой строки, которую я только что добавил в конце, строке, окруженной пробелами после нее. Если это так, я заменяю весь лот на Bear, а если нет, то это не причинит вреда, потому что я в следующий раз P
набираю только до первой встречающейся новой строки в пространстве образца, затем d
удаляю все это.
###OUTPUT###
Bear
Bear
pear
banana
Bear
Bear
И когда я говорю гибкий, я имею в виду это. Здесь он заменяет кошку на BrownBear и собаку на BlackBear :
printf %s\\n cat dog pear banana cat dog |
sed '1{x;s/^/ 1cat Brown 2dog Black /;x
};G;s/^\(.*\)\n.* [0-9]\1 \([^ ]*\) .*/\2Bear/;P;d'
###OUTPUT###
BrownBear
BlackBear
pear
banana
BrownBear
BlackBear
Конечно, вы можете значительно расширить содержание таблицы поиска - я взял идею из писем Грег Уббена по этому вопросу, когда в 90-х он описал, как он построил грубый калькулятор из одного sed s///
утверждения.
-r
вариант как синоним-E
для совместимости с GNU СЭД. OpenBSD и OS Xsed -E
будут интерпретировать экранированный канал как буквальный канал, а не как оператор чередования. Вот рабочая ссылка на справочную страницу NetBSD, а вот для OpenBSD, которой нет десяти лет.