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                    = [email protected]

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                    = [email protected]
4
  • What is the expected output you must state in the question. That way the query becomes totally unambiguous and avoid responder interpretation dependencies. Commented May 3, 2021 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. Commented May 3, 2021 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. Commented May 3, 2021 at 23:48
  • @guest_7 thank you for your feedback I have edited the question above accordingly. Commented May 4, 2021 at 8:12

2 Answers 2

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.

2
  • 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. Commented May 4, 2021 at 9:12
  • In that case, yes, the PERL proposal is the ideal solution IMHO, but you might be able to get sed to behave with: sed -e '/^[ req_distinguished_name ]/,/^[/s/^(commonName\s+=\s+)(.*$)/\1<replacement_value>/' Commented Nov 11, 2023 at 2:51

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.