Running the following command:

echo "hello-world" | tr "hello-world" "Hello World"

Returns Heddd-ddddd. I want it to return Hello World. I believe this is because tr is interpreting the SET1 argument as a range (from the tr manpage):

    all characters from CHAR1 to CHAR2 in ascending order

I have also tried:

echo ${"hello-world//hello-world/Hello World"}

Which returns:

bash: ${"hello-world//hello-world/Hello World"}: bad substitution

What is the preferred way to do this (translate all instances of a string to a different string)? Either with tr or another program.

  • 2
    put the hyphen at the end: echo 'hello-world' | tr 'hw-' 'HW ' – mosvy Dec 26 '18 at 17:58
  • @mosvy Thanks. This was just a simple example - what should I do when I have a more complex string with other instances of h/w/- that I don't want to affect? I've update the title to better reflect the actual problem - tr was just one approach I have tried. – Frayt Dec 26 '18 at 18:04
  • 2
    tr is for mapping one-to-one between sets of characters - for string replacements, you should use something like sed – steeldriver Dec 26 '18 at 18:08
  • ... your shell parameter expansion approach would also work, provided your original string is inside a variable e.g. str="hello-world" ; echo "${str/hello-world/Hello World}" - it won't work on string literals AFAIK – steeldriver Dec 26 '18 at 18:23

Just we need to escape the -

echo "hello-world" | tr "hello\-world" "Hello World"

Luckily we don't have trailing h or w in the context to give a wired result. So, its better to replace the first char of each string to upper case.

Using sed

echo "hello-world" | sed 's/-/ /g;s/\<./\U&/g'

You can

  • convert the hyphens with tr
  • convert the first letter in each word to upper case (and print the rest of each word ($i,2) without any conversion) with awk

    $ echo 'hello-world-peace' | tr '-' ' ' | \
     awk '{for(i=1;i<=NF;i++){ $i=toupper(substr($i,1,1)) substr($i,2) }} {print}'
    Hello World Peace

You can also use awk for the whole task,

  • convert the hyphens with gsub
  • convert the first letter in each word to upper case with toupper
  • and print the rest of each word ($i,2) without any conversion

    echo 'hello-world-peace' | \
     awk '{gsub("-"," "); for(i=1;i<=NF;i++) \
     { $i=toupper(substr($i,1,1)) substr($i,2) }} {print}'

This sed would work:

echo "hello-world" |sed -E -n 's/.(.*)-.(.*)/H\1 W\2/p'


Hello World

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.