Home > front end >  Using sed to uppercase all characters before "="
Using sed to uppercase all characters before "="

Time:06-04

I have the following string: abcd=efgh and I would like to uppercase all characters before the = to get ABCD=efgh.

After reading a bunch of posts, I tried the following:

echo "abcd=efgh" | sed -r 's/^(.*)=/\U\1\E=/'

But this returns: UabcdE=efgh

So with the command, I can capture the right group but the \U doesn't uppercase the capture group. Any idea? Thanks!

CodePudding user response:

As you discovvered, you're running into the difference between GNU sed and BSD sed; the latter is what ships on macOS. If you install GNU sed (e.g. the Homebrew gnu-sed package) and use that (probably installed as gsed), then your original attempt will work.

A more portable solution would be to use perl. Your original sed expression works unchanged:

$ echo "abcd=efgh"  |  perl -pe 's/^(.*)=/\U\1\E=/'       
ABCD=efgh

Although I would simplify the expression a bit and replace the echo | with a here-string:

$ perl -pe 's/^[^=]*/\U$&/' <<<'abcd=efgh'
ABCD=efgh

There are other tools you could use, but they don't drop right in with the same syntax as sed like perl does. For example, you could use shell builtins to split the string and then run tr on the half you want to capitalize:

IFS== read left right <<<abcd=efgh
printf '%s=%s\n' "$(tr a-z A-Z <<<"$left")" "$right"

If you're using zsh, you can use its built-in uppercase expansion instead of tr:

IFS== read left right <<<abcd=efgh
printf '%s=%s\n' "${(U)left}" "$right"

Newer bash versions can do it, too, but not the one that ships in /bin/ on macOS. You have to install a newer one (for example with Homebrew again), and then this works:

IFS== read left right <<<abcd=efgh
printf '%s=%s\n' "${left^^}" "$right"

CodePudding user response:

Plenty of solutions. Here one using awk:

awk -F= '{print toupper($1) "=" $2}' <<< 'abcd=efgh'
ABCD=efgh

CodePudding user response:

This might work for you (GNU sed):

sed 'h;y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/;G;s/=.*=/=/' file

Make a copy of the current line.

Translate all lowercase alpha to uppercase alpha.

Append the copy of the original line.

Remove the portion of the two lines from = to = and replace it by =.

Alternative:

sed 's/.*=/\U&/' file

CodePudding user response:

Simply add g modifier (works with GNU sed):

echo "abcd=efgh" | sed -r 's/^(.*)=/\U\1\E=/g'

CodePudding user response:

With bash and a regex:

s="abcd=efgh"

[[ "$s" =~ (.*)=(.*) ]] && s="${BASH_REMATCH[1]^^}=${BASH_REMATCH[2]}"

echo "$s"

Output:

ABCD=efgh
  • Related