6
\$\begingroup\$

I want to convert my_long_variable to myLongVariable in sed.

This works:

echo "my_long_variable" | sed -r 's/(^|_)([a-z])/\U\2/g' | sed -r 's/^(.)/\l\1/g'

Is there a more elegant way to do that with sed?

\$\endgroup\$
0
5
\$\begingroup\$

Why try to match for (^|_)? You are anyway modifying it at the end, so just skip the first character entirely:

echo "my_long_variable" | sed -r 's/_([a-z])/\U\1/gi' | sed -r 's/^([A-Z])/\l\1/'

The above pattern will take care of cases where you start with:

Some_var_Iable
\$\endgroup\$
5
\$\begingroup\$

First of all, prefer -E to -r; it's more portable.

However, since you're using the \U GNU extension in any case, this isn't that crucial.

Second, I assume echo is a stand-in for a more complex command. If there is in fact no complex command, consider using a Here String or a Here Doc instead.

Crucially, you don't need to fire up two Sed processes just to run two Sed commands. Sed is a complete programming language in itself. Just separate the two commands with a semicolon: sed 's/foo/bar/;s/frip/baz/'

However, in this case you don't even need that, because you only need a single substitution.

sed -E 's/_([a-z])/\U\1/g' <<< my_long_variable

There is another aspect here. You shouldn't often need to change case in scripts (and certainly not in Bash). But if you're doing this in your editor, you should use vi rather than a Bash script for the editing. \U and its relatives are standard features of vi, though not of Sed.

So within vi, on a line of text containing only the variable name, you can use:

:s/_\([a-z]\)/\U\1/g

This is portable (POSIX compliant) and will work on any system that has vi, even the most minimal implementation.

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Thanks! This is part of a code generation tool (with different modules using different languages with different conventions), so vi won't do, it needs to be automated. \$\endgroup\$ – Nicolas Raoul Nov 18 '16 at 4:49
  • \$\begingroup\$ @NicolasRaoul, gotcha! For scripted text edits, you may want to learn ex (the predecessor of vi), which is designed for editing text files (whereas Sed is the stream editor)—and is fully portable. I've written extensively on its use on the Unix & Linux Stack Exchange. \$\endgroup\$ – Wildcard Nov 18 '16 at 5:13
4
\$\begingroup\$

In addition to the other good suggestions, don't pipe sed to another invocation of sed, use a semi-colon to separate multiple commands.

Also you might want to make your toCamelCase method more generic, e.g.

echo "Something_with-a bit_of Variety" | sed -E 's/[ _-]([a-z])/\U\1/gi;s/^([A-Z])/\l\1/'

outputs

somethingWithABitOfVariety

or even

echo "Something & some_special! chars" | sed -E 's/[^a-z]+([a-z])/\U\1/gi;s/^([A-Z])/\l\1/'

outputs

somethingSomeSpecialChars
\$\endgroup\$
4
  • 1
    \$\begingroup\$ Semicolons are not portable to anything other than GNU sed. You can use -e to append more editing commands at the end, which is the portable way to do it. Other than that, welcome and good first post! \$\endgroup\$ – S.S. Anne Mar 11 '20 at 19:49
  • \$\begingroup\$ Fair point, but then neither is \U! \$\endgroup\$ – spikyjt Mar 11 '20 at 20:06
  • \$\begingroup\$ Not using multiple sed processes was already mentioned in Wildcard's answer. \$\endgroup\$ – Toby Speight Mar 17 '20 at 9:37
  • \$\begingroup\$ @TobySpeight you are correct - somehow I missed that! Should I downvote myself for skim reading?! Perhaps I should edit my answer just to demonstrate the general conversion to camel case from any string with special chars etc. \$\endgroup\$ – spikyjt Mar 19 '20 at 10:55

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.