Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Easiest way to capitalize a string within bash 3.2?

Tags:

bash

shell

macos

For example: var=dog and echo $var output is dog. Capitalize $var expected output Dog.

Tried multiple ways but just not getting the expected output. Some attempts:

echo $var | sed "s/[a-z]\&[:upper:]//"  #dog
echo $var | sed "s/([a-z])/[:upper:]/"  #dog
like image 344
MrPizzaFace Avatar asked Dec 01 '22 17:12

MrPizzaFace


1 Answers

tl;dr:

  • macOS, with Unicode support, OR cross-platform, but ASCII-only, and for background information:

    • See the tr solution below.
  • GNU utilities, with Unicode support (Linux: preinstalled; macOS: installable via Homebrew):

    • sed 's/^./\u&/' <<<'dog' # -> 'Dog'
      • macOS: after installing with brew install gnu-sed, use gsed instead of sed
    • awk alternative: see dev-null's answer
      • macOS: after installing with brew install gawk, use gawk instead of awk.
  • Cross-platform, with Unicode support:

    • perl: see dawg's answer
    • python: see idjaw's answer
  • Bash 4+, with Unicode support, which on macOS you can also install with Homebrew:

    • echo "${var^}"

Try

var='dog'
echo "$(tr '[:lower:]' '[:upper:]' <<<"${var:0:1}")${var:1}" # -> 'Dog'
  • tr '[:lower:]' '[:upper:]' <<<"${var:0:1}" extracts the 1st char from $var (${var:0:1}) and uses tr to translate it to uppercase.

  • ${var:1} returns everything from the 2nd char in $var's value.

Note that this solution is Unicode-aware[1], unlike the macOS awk and Python 2.x solutions Update: @idjaw fixed the Python 2.x solution with .decode('utf-8'), and presumably also slightly faster than them (tr is lighter-weight than awk and python).

[1] This applies to the BSD tr version that comes with macOS. GNU tr, by contrast, does not handle non-ASCII characters correctly - as John1024 notes, according to Wikipedia, "Most versions of tr, including GNU tr and classic Unix tr, operate on single-byte characters and are not Unicode compliant.".


As for your attempt at a sed solution:

Using macOS's (BSD) sed, I'm not aware of any substring-manipulation features.

If you had GNU sed - which you could install via Homebrew - you could use the following:

sed 's/^./\u&/' <<<'dog' # -> 'Dog'

\u tells GNU Sed to capitalize the following letter. Sadly, you can't do that with macOS's Sed.

[:upper:] only ever works as a matching character class, it never performs transformation, which is why your command didn't work.
The only exception is tr, where you can pair an [:upper:] with a [:lower:] to effect transformation, as in my solution above.


Sneak preview of a Bash 4+ solution:

var='dog'; echo "${var^}"
like image 134
mklement0 Avatar answered Dec 16 '22 10:12

mklement0