匹配一个模式并替换下面键值对的值

匹配一个模式并替换下面键值对的值

我正在尝试修改包含如下部分的文件:

[ policy_strict ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req_distinguished_name ]
countryName                     = UK
stateOrProvinceName             = Scotland
localityName                    = Glasgow
0.organizationName              = aworkplace
organizationalUnitName          = eng
commonName                      = my.webiste.com
emailAddress                    = [email protected]

我想修改common name最后一节中字段的值。

我认为应该有一个类似的解决方案这个解决方案

sed '/[铲子]/,/^$/ s/启用 = 0/启用 = 1/'

不同之处在于,被替换的值不是 sed 命令中匹配的表达式的一部分。

更新

根据评论进行一些澄清,目标是仅更改commonNamereq_distinguished_name部分中的字段。例如

[ policy_strict ]
countryName             = match
stateOrProvinceName     = match
organizationName        = match
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ policy_loose ]
countryName             = optional
stateOrProvinceName     = optional
localityName            = optional
organizationName        = optional
organizationalUnitName  = optional
commonName              = supplied
emailAddress            = optional

[ req_distinguished_name ]
countryName                     = UK
stateOrProvinceName             = Scotland
localityName                    = Glasgow
0.organizationName              = aworkplace
organizationalUnitName          = eng
commonName                      = adifferentvaluetotheoneintheabovesnippet
emailAddress                    = [email protected]

答案1

GNU sed在扩展正则表达式模式下,-E我们使用范围运算符,来选择正确的块,并在该块内使用s/正则表达式/repl/将右行归零以进行编辑。

sed -Ee '
  /\[ req_distinguished_name ]/,/^$/s/^(\s*commonName\s*=).*/\1__NEWVALUE__/
' file

答案2

假设您想要替换文件中属性 commonName 的值,并且您愿意替换如此命名的任何属性的所有值,则以下操作应该有效(并假设 PCRE):

s/(^commonName\s+=\s*)(.*)$/\1<your replacement text here>/

例如,假设您想要设置新值“foo”,那么您的示例文件将运行以下内容:

s/(^commonName\s+=\s*)(.*)$/\1foo/

应该导致所有其他行保持不变,并且 commonName 值全部替换为:

commonName              = foo
commonName              = foo
and
commonName                      = foo

如果您只想替换最后一个,那么最简单的方法是跳过程序的早期部分,直到找到节标记,然后使用上面的 s/// 结构替换第一个匹配项,然后停止编辑。

更新:如上所述,您应该能够在(例如 PERL)中完成此操作,方法是首先找到要编辑的块的块头,然后编辑(应用正则表达式替换)直到到达下一个块头,然后忽略文件的其余部分。在 Perl 中,这可能看起来像:

#!/usr/bin/env perl -pi.orig

while (<> !~ /\[ req_distinguished_name \]/) { # do nothing
};
while (<> !~ /^\[\s*[\w\d_+]\s*\]/) { s/^(commonName\s*=\s*)(.*)$/\1<repl>/; }
while (!eof()) { <>; }

这将编辑命令行参数中指定的文件,并将未修改文件的备份副本保存在“.orig”中。

这应该非常接近你想要的。

相关内容