Search code examples
stringshelllowercasecapitalizationcapitalize

lowercase + capitalize + concatenate words of a string in shell (e.g. bash)


How to capitalize+concatenate words of a string?
(first letter uppercase and all other other letters lowercase)

example:
input = "jAMeS bOnD"
output = "JamesBond"


Solution

  • String manipulation available in version 4:

    • ${variable,,} to lowercase all letters
    • ${variable^} to uppercase first letter of each word
    • use ${words[*]^} instead of ${words[@]^} to save some script lines

    And other improvements from mklement0 (see his comments):

    • Variable names in lower-case because upper-case ones may conflict with environment variables
    • Give meaningful names to variables (e.g. ARRAY -> words)
    • Use local to avoid impacting IFS outside the function (once is enougth)
    • Use local for all other local variables ( variable can be first declared, and later assigned)
    • ARRAY=( $LOWERCASE ) may expands globs (filename wildcards)
      • temporarily disable Pathname Expansion using set -f or shopt -so noglob
      • or use read -ra words <<< "$input" instead of words=( $input )

    Ultimate function:

    capitalize_remove_spaces()
    {
      local words IFS
      read -ra words <<< "${@,,}"
      IFS=''
      echo "${words[*]^}"
    }
    

    If you want to keep alphanumeric characters only, extends the IFS built-in variable just before the read -ra words operation:

    capitalize_remove_punctuation()
    {
      local words IFS=$' \t\n-\'.,;!:*?' #Handle hyphenated names and punctuation
      read -ra words <<< "${@,,}"
      IFS=''
      echo "${words[*]^}"
    }
    

    Examples:

    > capitalize_remove_spaces 'jAMeS bOnD'
    JamesBond
    
    > capitalize_remove_spaces 'jAMeS bOnD *'
    JamesBond*
    
    > capitalize_remove_spaces 'Jean-luc GRAND-PIERRE'
    Jean-lucGrand-pierre
    
    > capitalize_remove_punctuation 'Jean-luc GRAND-PIERRE'
    JeanLucGrandPierre
    
    > capitalize_remove_punctuation 'Jean-luc GRAND-PIERRE *'
    JeanLucGrandPierre