0

I'm trying to modify a file that contains sections like this:

[ 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                    = myemail@email.com

I want to modify the value of the common name field in the last section.

I think there should be a solution similar to this solution.

sed '/[shovel]/,/^$/ s/enabled = 0/enabled = 1/'

With the difference that, the value being replaced is not part of the expression being matched on in the sed command.

Update

Some clarification based on the comments the goal is to change the commonName field in the req_distinguished_name section only. e.g.

[ 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                    = myemail@email.com
4
  • What is the expected output you must state in the question. That way the query becomes totally unambiguous and avoid responder interpretation dependencies. – guest_7 May 3 at 23:41
  • Sometimes you state you want the edit only in the last section ....then someplace else you say the substitution needs to happen for every occurrence in the file. Can you clarify. – guest_7 May 3 at 23:43
  • Is the last section name fixed or known in advance? Because the solutions become totally different based on that fact. So you need to state this information in the question statement also. – guest_7 May 3 at 23:48
  • @guest_7 thank you for your feedback I have edited the question above accordingly. – Allan M May 4 at 8:12
1

GNU sed in extended regex mode -E we use the range operator , to select the right block and within that block use the regex of the s/regex/repl/ to zero in on the right line to make the edits.

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

Assuming that you want to replace the value of the attribute commonName in the file and you are willing to replace all values of any attribute so named, the following should work (and assuming PCRE):

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

For example, say you want to make the new value "foo", then the your example file run through this:

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

Should result in all other lines remaining the same and the commonName values all being replaced as:

commonName              = foo
commonName              = foo
and
commonName                      = foo

If you want to replace only the last one, then the easiest thing is to have some earlier part of your program skip until you find the section tag, then replace the first occurrence using the above s/// construct, then stop editing.

Update: As stated, you should be able to accomplish this in (e.g. PERL) by first finding the block header of the block you want to edit and then editing (applying the regular expression substitution) until you reach the next block header and then ignoring the rest of the file. In perl, that might look like:

#!/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()) { <>; }

This will edit the files specified on the command line arguments in place and save a backup copy of the unmodified files in ".orig".

That should be pretty close to what you want.

1
  • Hi Owen thanks for your response. I have edited the question a little as someone else pointed out I hadn't made my goal clear enough. I think in your last paragraph you touch on what my actual goal is. I am essentially trying to figure out a sed command that will replace only the value of the commonName field after the [ req_distinguished_name ] section. – Allan M May 4 at 9:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.