Vinoth Selvaraj
Vinoth Selvaraj

Reputation: 301

Linux sed expression to convert the camelCase keys to underscore strings

I could not get the regex to convert only the key from a key value pair from camel case to underscore sting.

The expressions like sed -E 's/\B[A-Z]/_\U&/g' converts the full value, but I would like to limit the conversion only to the key here.

 $ echo UserPoolId="eu-west-1_6K6Q2bT9c" | sed -E 's/\B[A-Z]/_\U&/g' 
   User_Pool_Id=eu-west-1_6_K6_Q2b_T9c

but i would like to get User_Pool_Id=eu-west-1_6K6Q2bT9c

Upvotes: 0

Views: 160

Answers (4)

Renaud Pacalet
Renaud Pacalet

Reputation: 29345

If you have only one = sign and you want to modify the camel case before the = sign, with GNU sed you can iterate until all substitutions are done:

echo UserPoolId="eu-west-1_6K6Q2bT9c" | sed -E ':a;s/([a-z])([A-Z].*=.*)/\1_\2/;ta'
User_Pool_Id=eu-west-1_6K6Q2bT9c

:a sets label a, ta branches to label a if the previous s command substituted something. The s command in the loop inserts a _ between a lower case and an upper case before the equal sign.

In your example this will first insert a _ between User and Pool, and then between Pool and Id.

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 204548

With GNU awk for the 3rd arg to match() and gensub():

$ echo 'UserPoolId="eu-west-1_6K6Q2bT9c"' |
    awk 'match($0,/([^=]+=)"(.*)"/,a) { $0=gensub(/([[:lower:]])([[:upper:]])/,"\\1_\\2","g",a[1]) a[2]} 1'
User_Pool_Id=eu-west-1_6K6Q2bT9c

I don't know if it's what you'd want for this case or not but anyway:

$ echo 'UserPoolID="eu-west-1_6K6Q2bT9c"' |
    awk 'match($0,/([^=]+=)"(.*)"/,a) { $0=gensub(/([[:lower:]])([[:upper:]])/,"\\1_\\2","g",a[1]) a[2]} 1'
User_Pool_ID=eu-west-1_6K6Q2bT9c

Note that ID remains as _ID and isn't converted to _I_D.

Upvotes: 2

potong
potong

Reputation: 58558

This might work for you (GNU sed):

sed 's/=/&\n/;h;s/\B[[:upper:]]/_&/g;G;s/\n.*\n//' file

Introduce a newline after the = and copy the result to the hold space.

Insert underscores in the required places.

Append the copy to the current line and remove the middle, leaving the answer.

Upvotes: 1

tripleee
tripleee

Reputation: 189900

Doing this in sed is somewhat challenging because you need a more complex regex and a more complex script. Perhaps a better solution would be to use the shell's substitution facilities to isolate the part you want to operate on.

string='UserPoolId="eu-west-1_6K6Q2bT9c"'
prefix=${string%%=*}
suffix=${string#"$prefix"}
sed -E -e 's/\B[A-Z]/_\U&/g' -e "s/\$/$suffix/" <<<"$prefix"

Bash also has built-in parameter expansion to convert the first character of a string to upper case, but perhaps this is sufficient to solve your immediate problem.

Upvotes: 1

Related Questions