Использование sed для поиска замены в файле, но не в строках, соответствующих нескольким шаблонам - PullRequest
0 голосов
/ 31 мая 2018

У меня есть файл XML, который я нахожу и заменяю emails и usernames. Это все хорошо, но нужно избегать дублирования электронных писем пользователей и т. Д. Я хочу пропустить элементы XML определенных типов.

Я могу сделать это, если я хочу пропустить ОДНО определенное время, т. Е.

/ApplicationUser/!s/"user.name"/"user.name@abc.com"/g

Но нет, если я попытаюсь выполнить несколько команд по одной команде sed

/(OtherElement|ApplicationUser)/!s/"user.name"/"user.name@abc.com"/g

ИЛИ

/\(OtherElement\|ApplicationUser\)/!s/"user.name"/"user.name@abc.com"/g

ИЛИ

/\(OtherElement|ApplicationUser\)/!s/"user.name"/"user.name@abc.com"/g

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

Ответы [ 3 ]

0 голосов
/ 31 мая 2018

Это может сработать для вас (GNU sed):

sed '/OtherElement\|ApplicationUser/b;s/"user.name"/"user.name@abc.com"/g file

При обнаружении строки, которую вы не хотите обрабатывать, разбить, извлечь следующую и повторить.

0 голосов
/ 31 мая 2018

Просто используйте awk и избегайте запутанной, обратной логики (if X do NOT do Y but do Y for everything else против простого if NOT X do Y) и конструкций, зависящих от версии, которые вы получаете с помощью sed.

awk '!/OtherElement|ApplicationUser/{ gsub(/"user.name"/,"\"user.name@abc.com\"") } 1' file

Это ясно, просто, расширяемый и будет работать с любым awk в любой оболочке на любой машине UNIX.

0 голосов
/ 31 мая 2018

Таким образом, синтаксис регулярного выражения зависит от используемой вами версии sed.

Прежде всего, согласно спецификации POSIX, базовые регулярные выражения (BRE) не поддерживают чередование .Однако инструменты не обязательно следуют спецификации и, в частности, разные версии sed ведут себя по-разному.

Все приведенные ниже примеры обрабатывают этот файл:

$ cat sed-re-test.txt
OtherElement "user.name"
OnlyReplaceMe "user.name"
ApplicationUser "user.name"

GNU sed

Вариант GNU sed BRE поддерживает чередование, но метасимвол | (вместе с ( и )) должен быть экранирован с помощью \.Если вы используете флаг -E для включения расширенных регулярных выражений (ERE), то метасимволы не должны быть экранированы .

$ sed --version
sed (GNU sed) 4.4
<...SNIP...>

вариант GNU sed BRE (с экранированными метасимволами): WORKS

$ cat sed-re-test.txt  | sed '/\(OtherElement\|ApplicationUser\)/!s/"user.name"/"user.name@abc.com"/g'
OtherElement "user.name"
OnlyReplaceMe "user.name@abc.com"
ApplicationUser "user.name"

GNU sed ERE (с метасимволами без экранирования): WORKS

$ cat sed-re-test.txt  | sed -E '/(OtherElement|ApplicationUser)/!s/"user.name"/"user.name@abc.com"/g'
OtherElement "user.name"
OnlyReplaceMe "user.name@abc.com"
ApplicationUser "user.name"

BSD / MacOS sed

BSD sed не поддерживает чередование в режиме BRE.Вы должны использовать -E, чтобы включить поддержку чередования.

Нет --version флаг, поэтому для идентификации ОС необходимо сделать:

$ uname -s
OpenBSD

BSD sed BRE (с метасимволами с экранированием и без экранирования): НЕ РАБОТАЕТ

$ cat sed-re-test.txt  | sed '/\(OtherElement\|ApplicationUser\)/! s/"user.name"/"user.name@abc.com"/'
OtherElement "user.name@abc.com"
OnlyReplaceMe "user.name@abc.com"
ApplicationUser "user.name@abc.com"

$ cat sed-re-test.txt  | sed '/(OtherElement|ApplicationUser)/! s/"user.name"/"user.name@abc.com"/'
OtherElement "user.name@abc.com"
OnlyReplaceMe "user.name@abc.com"
ApplicationUser "user.name@abc.com"

BSD sed ERE (с метасимволами без экранирования): WORKS

$ cat sed-re-test.txt  | sed -E '/(OtherElement|ApplicationUser)/! s/"user.name"/"user.name@abc.com"/'
OtherElement "user.name"
OnlyReplaceMe "user.name@abc.com"
ApplicationUser "user.name"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...