Issue
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!
Solution
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"
Answered By - Mark Reed Answer Checked By - Gilberto Lyons (WPSolving Admin)