使用sed在文件中查找替换但不在匹配多个模式的行上查找

时间:2018-05-31 04:46:50

标签: regex sed

我找到了XML个文件,正在替换emailsusernames。 这一切都很好,但要避免一些重复的用户电子邮件等。我想跳过特定类型的XML元素。

如果我想跳过一个特定时间,我就可以这样做。

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

但如果我在一个sed命令上尝试多次

,那就不行了
/(OtherElement|ApplicationUser)/!s/"user.name"/"user.name@abc.com"/g

OR

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

OR

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

如果相关,我正在加载文件中的命令。我假设它在开始时与我的模式有关,试图匹配1个或多个单词,但不确定。

3 个答案:

答案 0 :(得分:1)

因此,正则表达式语法取决于您正在使用的sed版本。

首先,根据POSIX规范,basic regular expressions (BRE) do not support alternation。但是,工具不一定遵循规范,特别是不同版本的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"

答案 1 :(得分:0)

这可能适合你(GNU sed):

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

在遇到你不想处理的一行时,爆发,获取下一行并重复。

答案 2 :(得分:0)

只需使用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

这是清楚,简单,可扩展的,并且可以在任何UNIX机器上的任何shell中使用任何awk。