9
\$\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

3 Answers 3

7
\$\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\$
3
  • 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\$ Commented Nov 18, 2016 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
    Commented Nov 18, 2016 at 5:13
  • \$\begingroup\$ The vi command :s/_\([a-z]\)/\U\1/g fails to convert the first character of the variable name to upper case. (Edit: I guess that's what OP desired.) \$\endgroup\$
    – nibot
    Commented Nov 3, 2023 at 17:20
6
\$\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\$
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
    Commented Mar 11, 2020 at 19:49
  • \$\begingroup\$ Fair point, but then neither is \U! \$\endgroup\$
    – spikyjt
    Commented Mar 11, 2020 at 20:06
  • \$\begingroup\$ Not using multiple sed processes was already mentioned in Wildcard's answer. \$\endgroup\$ Commented Mar 17, 2020 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
    Commented Mar 19, 2020 at 10:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.