Kamlesh Gallani Kamlesh Gallani - 14 days ago 4
Bash Question

Capitalize each input string in shell script

I am accepting a few strings as user input to my script like -

read -p "User's full name : " FULLNAME
read -p "User's Manager's name : " MGRNAME
.
.


I want all input strings be capitalized, i.e. capitalize each word in the input string.

I wrote a simple function like -

capitalize()
{
$1=`echo ${$1}|sed -e "s/\b\(.\)/\u\1/g"`
}


and called this function as -

capitalize FULLNAME


It is giving the below error -

line 77: ${$1}: bad substitution


Also tried indirect expansion -

capitalize()
{
$1=`echo ${!1^}`
}


It throws the below error -

line 77: FULLNAME=Kamlesh: command not found


Please help with the correct syntax or any other way to achieve this.

Sample Output - I am reading the input in FULLNAME variable. When I am calling capitalize(), it should update the value within FULLNAME variable itself.

For e.g., if the user input is - "kamlesh gallani"

If I call capitalize FULLNAME now, then FULLNAME should contain "Kamlesh Gallani"

Answer

The below is tested in ksh93u+ (2012-08-01):

capitalize_words() {
    typeset string string_out
    string=$1
    string_out=''
    read -r -A words <<<"$string"
    for word in "${words[@]}"; do
      [[ -n "$string_out" ]] && string_out+=" "
      first_letter=${word:0:1}
      rest=${word:1}
      string_out+="$(printf '%s\n' "$first_letter" | tr '[:lower:]' '[:upper:]')"
      string_out+="$rest"
    done
    echo "$string_out"
}

Thereafter:

$ capitalize_words 'kamlesh gallani'
Kamlesh Gallani

...or, to modify a variable:

fullname='kamlesh gallani'
fullname=$(capitalize_words "$fullname")

If you really want this to operate indirectly, you can do that:

capitalize_words_inplace() {
  typeset -n var="$1"
  var=$(capitalize_words "$var")
}

...thereafter:

$ fullname='kamlesh gallani'
$ capitalize_words_inplace fullname
$ echo "$fullname"
Kamlesh Gallani