1

I have been provided a %post script inside a spec file to edit a config file (called foo). I have ben tasked with writing another, almost identical script to edit a file called 'bar'.

While my solution for 'bar' technically works, it is dramatically different semantically. The custodian is requesting I rewrite it for consistency.

foo.groovy before

messageQueue.secretKey = "<ENTER-KEY-HERE>" 

foo.groovy after

messageQueue.secretKey = "y775hUYKR1Bm4gUWNRbzqg65"

The script given me is the following:

%define oauth_client_Secret \
echo "  Setting the message queue secret key..." \
MESSAGEQUEUESECRETKEY=`dd if=/dev/urandom count=16 bs=1 2>/dev/null | base64` \
for config_file in `find /opt/foo/etc -name *.groovy` \
do \
sed -i -e "/messageQueue.secretKey/ { " \\\
        -e "    s?^//\s*??" \\\
        -e "    s?<ENTER-KEY-HERE>?${MESSAGEQUEUESECRETKEY}?" \\\
        -e "}" \\\
    ${config_file} \
done

What I am trying to figure out:

  1. What does this regex do? s?^//\s*??" I assume it is looking for an equals sign?
  2. What is the purpose of the trailing slashes ? \\\
  3. Why did the previous author surround the expression in brackets { } ?

For reference, here is my script (for bar), that I am trying to rewrite to match the above script (for foo)

bar.groovy before

clientSecret:"<ENTER-CLIENTSECRET-HERE>",

bar.groovy after

clientSecret:"4gUWNRbzqg65y775hUYKR1Bm",

bar script

%define oauth_client_Secret \
echo "  Generating oauth clientSecret..." \
MESSAGEQUEUESECRETKEY=`dd if=/dev/urandom count=16 bs=1 2>/dev/null | base64` \
for config_file in `find /opt/bar/etc -name *.groovy` \
do \
sed -i "s/<ENTER-CLIENTSECRET-HERE>/${MESSAGEQUEUESECRETKEY}/g" ${config_file} \
done
2

On any line containing the string messageQueue.secretKey it removes the string // and any spaces that follow if it exists at the start of the line and replaces the first occurrence of <ENTER-KEY-HERE> with the contents of the shell variable ${MESSAGEQUEUESECRETKEY}. The { curlies confine the removals/replacements to only lines containing the string messageQueue.secretKey. These operations are performed on the file referenced by the shell variable ${config_file}.

The \\\backslashes continue the statement into one long line - escaping the immediately following \newline character when the script is read in by the shell. Three are necessary because those are contained within " double-quotes and the backslash escapes itself in that context. So the shell gets one escaped newline and sed gets one escaped newline. Though, while I don't know about the shell in this context, I don't believe sed would care if the newlines were not escaped at all anyway.

1
  1. What does this regex do? s?^//\s*??"

Remove the // and any spaces following from the line start on lines that contain messageQueue.secretKey with:

  • the question mark ? as the pattern delimiter
  • ^ matches the beginning of a line
  • // matches exactly that (on a side note that is the reason to use the question mark as the pattern delimiter instead of the more common / which prevents quite a bit of escaping because otherwise the regex would be s/^\/\/\s*//
  • \s* is GNU sed specific to match or or more whitespace space and/or Tab ; POSIX sed would use [:space:]

And @mikeserv has just posted an even more comprehensive answer...

3
  • In truth, it was posted before this, but yours has pretty bullets, so I voted for it. More importantly though - you point out the GNU specific syntax, which also applies to -i.
    – mikeserv
    Jun 17 '14 at 18:48
  • :) same here. Got somewhat distracted halfway through and then when I got back to it I noticed your answer had popped up but didn't want to discard what I had.
    – HBruijn
    Jun 17 '14 at 18:51
  • I'm glad you didn't.
    – mikeserv
    Jun 17 '14 at 18:51

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.