0

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"

Kamlesh Gallani
  • 701
  • 1
  • 9
  • 16
  • 2
    You're tagged both ksh and bash. Which one? There are syntax extensions in bash 4.x that are relevant here that ksh doesn't have. **Please tag only for the shell you're actually using.** – Charles Duffy Nov 18 '16 at 16:27
  • BTW, as for `${$1}`, if you want that to work then you should be looking up [indirect expansion](http://mywiki.wooledge.org/BashFAQ/006#Evaluating_indirect.2Freference_variables). – Charles Duffy Nov 18 '16 at 16:28
  • 3
    (...on a different note, all-caps variable names are used by variables with meaning to the system and shell, whereas the namespace of variables with at least one lowercase character is reserved for application use. Thus, your scripts should use lowercase variables to avoid overwriting something with meaning to the operating system by mistake. This is specified by the POSIX rules for environment variables, but setting a shell variable that overlaps the name of an environment variable will overwrite the latter, so the rule applies in both places). – Charles Duffy Nov 18 '16 at 16:31
  • BTW, if you showed sample output to distinguish whether you want `Some Word` or `SOME WORD` as your output, that would be helpful; right now the question is somewhat ambiguous. – Charles Duffy Nov 18 '16 at 16:34
  • 1
    (...btw, your regex is using some PCRE-isms -- generally `sed` ships using BRE, and will often have an option or extension that can be given to enable ERE, but PCRE support is rare. Does `echo "hello world" | sed -e "s/\b\(.\)/\u\1/g"` actually work on your platform? If so, what's your OS?) – Charles Duffy Nov 18 '16 at 16:36
  • @CharlesDuffy, yes it works on my machine - Its Red Hat Enterprise Linux Server release 6.5. `echo "hello world" | sed -e "s/\b\(.\)/\u\1/g" Hello World` – Kamlesh Gallani Nov 21 '16 at 17:32
  • Ahh. Be aware that `\b` and `\u` aren't guaranteed to work on other platforms. – Charles Duffy Nov 21 '16 at 17:37
  • By the way -- calling out your edits with an `EDIT:` marker is actually frowned on here: Questions should be written to be as readable as possible for someone looking at them for the first time, so content that's edited in should be done so in a manner that optimizes flow; for folks who want to see history, there's a link to see edit history with full diffs. – Charles Duffy Nov 21 '16 at 17:39
  • Thanks for your valuable inputs. Please bear with me as I still new to this world and trying to learn. I tried indirect expansion too, but it did not work, Edited my question to include the case. – Kamlesh Gallani Nov 21 '16 at 18:04
  • The `^` syntax in a bashism (and only available in very new bash, not anything prior to 4.x), not expected to work in ksh. Frankly, why are you bothering with indirect expansion here? Do you have any good reason to run `capitalize FULLNAME`, and not `FULLNAME=$(capitalize "$FULLNAME")`? – Charles Duffy Nov 21 '16 at 18:06
  • That said, I've amended my answer to show an in-place implementation with namevars, tested against ksh93u+. – Charles Duffy Nov 21 '16 at 18:10

5 Answers5

4

Using bash's parameter expansion, assuming variable var:

${var^}  ## Only first character
${var^^} ## All characters

Example:

$ foo=bar

$ echo "${foo^}"
Bar

$ echo "${foo^^}"
BAR
agc
  • 7,973
  • 2
  • 29
  • 50
heemayl
  • 39,294
  • 7
  • 70
  • 76
3

This will Uppercase Everything:

printf '%s\n' "$string" | tr '[:lower:]' '[:upper:]'

As you edited your question to Uppercase only first character of each word, Please try the following:

read -p "User's full name : " FULLNAME
capitalize()
{
        echo $* | sed -e "s/\b\(.\)/\u\1/g"

}
capitalize $FULLNAME
Farhad Farahi
  • 35,528
  • 7
  • 73
  • 70
2

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
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
1

Many bash-isms and ksh-isms, here is another that runs entirely within the shell.

capitalize()
{
    (typeset -u word=${1:?} && echo "$word")
}

The subshell assures the variable word is really local.

Henk Langeveld
  • 8,088
  • 1
  • 43
  • 57
  • 1
    At minimum, I'd suggest quoting the expansion of `$word` -- otherwise you're expanding globs, coalescing tabs or runs of spaces into a single space each, etc. – Charles Duffy Nov 21 '16 at 17:40
0

This method seems a bit roundabout, but it avoids bashisms, kshisms, and juggling variables:

printf "User's full name: "; FULLNAME=`head -n 1 | capitalize -c`; echo "$FULLNAME"
User's full name: ed ward
Ed Ward

The capitilize util can be found in Ubuntu's xviewg package, but it's inessential -- there are many ways to capitalize.

Community
  • 1
  • 1
agc
  • 7,973
  • 2
  • 29
  • 50
  • The OP wants to capitalize only the first letter of each word, not the entire strings. Also, `echo -n` is poorly-defined by POSIX -- consider using `printf` instead -- and all-uppercase variable names are in a space used by environment variable names with meaning to the shell or system, so (since defining a shell variable with a name that overlaps an environment variable overwrites the latter) there's less risk of conflict with something important if you use lowercase names for your own variables. See http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap08.html, fourth paragraph. – Charles Duffy Nov 21 '16 at 17:51
  • ...re: `echo -n`, see http://pubs.opengroup.org/onlinepubs/009695399/utilities/echo.html, specifying that output of `echo` when `-n` is passed is completely implementation-defined. – Charles Duffy Nov 21 '16 at 17:52
  • ...also, `echo $FULLNAME` vs `echo "$FULLNAME"` means you're expanding globs and replacing characters found in `IFS` with whitespace. – Charles Duffy Nov 21 '16 at 17:56
  • @CharlesDuffy, thanks, I'll fix that -- it seems my *all caps* answer preceded the OP's revised *first letter* version. The rest of your comments are excellent general advice, whereas I'm hopeing to *minimize* the confused OP's learning curve, i.e. "baby steps". – agc Nov 21 '16 at 19:31
  • I'd argue that if someone is an absolute beginner, it's *more* important to teach them the right way to do things at that point, as opposed to less; unlearning and re-learning wrong things later is more difficult and error-prone than learning right things in the first place. – Charles Duffy Nov 21 '16 at 20:41
  • @CharlesDuffy, surely not everybody is inclined to learn (or guide) the same way. We advocates for "baby steps" allow our baby to start out clumsy, to bump into things, crash, get dirty, and even fall down painfully. The resulting scuffs and bruises are offset by a more rapid progress, (or the useful illusion thereof), and less of the tedium of rote learning corner case bug cautions that some will never fully appreciate (or perhaps fear too much) unless we let the bugs really bite 'em. Its an interesting topic, but any more of this probably belongs on _meta_. – agc Nov 22 '16 at 04:37