How to uppercase the command line argument?

I searched SO and found that to uppercase a string following would work

str="Some string"
echo ${str^^}

But I tried to do a similar thing on a command-line argument, which gave me the following error


             ## Output
echo ${1^^}  ## line 3: ${1^^}: bad substitution
echo {$1^^}  ## No error, but output was still smaller case i.e. no effect

How could we do this?

Asked By: mtk


The syntax str^^ which you are trying is available from Bash 4.0 and above. Perhaps yours is an older version (or you ran the script with sh explicitly):

Try this:

str="Some string"
printf '%sn' "$str" | awk '{ print toupper($0) }'
Answered By: Guru
echo "lowercase" | tr a-z A-Z


Answered By: Johner Ramirez

Be careful with tr unless A-Z is all you use. For other locales even ‘[:lower:]’ ‘[:upper:]’ fails, only awk’s toupper and bash (v4+) works

$ str="abcåäö"
$ echo "$str"|tr '/a-z/' '/A-Z/'
$ echo "$str"|LC_ALL=sv_SE tr '[:lower:]' '[:upper:]'
$ echo "$str"|awk '{print toupper($0)}'
$ echo ${str^^} # Bash 4.0 and later
$ echo ${STR,,}
Answered By: lpaseen

If someone is still getting error trying ${str^^}, you can try python -c or perl It is likely because bash version is lower than 4.

But, so far bash 4 or over is working swiftly with the existing solution.

L2U="I will be upper"

Using python -c in bash

python -c "print('$L2U'.upper())"

Similarly it also can be used to capitalise with:

service=" on home"
python -c "print('$service'.capitalize())" on home

Using perl

echo $L2U | perl -ne 'print "U$_"'
Answered By: Rakib Fiha

Alternatively, you could switch to ksh or zsh which have had case conversion support for decades (long before bash‘s ${var^^} added in 4.0), though with a different syntax:

#! /bin/ksh -
typeset -u upper="$1"
printf '%sn' "$upper"

(also works with zsh; note that in pdksh/mksh, that only works for ASCII letters).

With zsh, you can also use the U parameter expansion flag or the csh style¹ u modifier:

#! /bin/zsh -
printf '%sn' "${(U)1}" "$1:u"

POSIXLY, you can use:

awk -- 'BEGIN{print toupper(ARGV[1])}' "$1"

There’s also:

printf '%sn' "$1" | tr '[:lower:]' '[:upper:]'

But in a few implementations, including GNU tr, that only works for single-byte characters (so in UTF-8 locales, only on ASCII letters, not accented letters of the Latin alphabet, not ligatures, not letters from other alphabets that also have a concept of case such as the Greek or Cyrillic alphabets).

In practice, none of those work for characters that don’t have a single-character uppercase version such as whose uppercase is FFI or the German ß. perl‘s uc (upper case) would work for those:

$ perl -CSA -le 'print uc for @ARGV' -- groß suffix

Here with -CLSA to specify that the Stdio streams and Arguments are meant to be encoded in UTF-8 as long as UTF-8 is the charmap used in the Locale.

¹ though that modifier specifically is originally from zsh, already there in 1.0 from 1990, copied by tcsh later in 1992 for 6.01.03.

Answered By: Stéphane Chazelas
Categories: Answers Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.