I've tried Googling this and tested every permutation I could come up with, but I'm just not getting it. :(

I have a function which accepts an identified input string:

[user@Dreadnaught /]$ myfunction -w InputString

The function has several input options, so I need to identify that I'm passing my string to the -w option. The string I'm getting from another program has dashes in it:


I can remove those dashes when testing an echo:

[user@Dreadnaught /]$ echo "In-put-St-ring" |tr -d -

But I can't figure out how to strip the dashes when passing to the function. I've tried (unsuccessfully):

[user@Dreadnaught /]$ OldString="In-put-St-ring"
[user@Dreadnaught /]$ echo $OldString
[user@Dreadnaught /]$ NewString=$OldString|tr -d -
[user@Dreadnaught /]$ echo $NewString

[user@Dreadnaught /]$ NewString=$($OldString|tr -d -)
-ash: In-put-St-ring: not found
[user@Dreadnaught /]$ NewString=$("$OldString"|tr -d -)
-ash: In-put-St-ring: not found
[user@Dreadnaught /]$ NewString=$(""$OldString"|tr -d -")
-ash: In-put-St-ring|tr -d -: not found


[user@Dreadnaught /]$ myfunction -w $("In-put-St-ring" |tr -d -)
-ash: In-put-St-ring: not found
myfunction: option requires an argument -- 'w'

and... a few more.

I'm sure it's simple for someone with more bash experience than me, but I'm stumped. Thanks for your help!

  • Does your function honor the -- option, to "Delimit the option list"? – Xen2050 Mar 16 at 4:37

You forgot to use echo.

A pipe doesn't send variables to a command – a pipe connects one command's output to the other command's input. That is, the whole echo "In-put-St-ring" is first processed and only then its output is sent to tr; not the other way around.

In other words, every time a pipe is used, you can interpret it like this:

(echo "$OldString") | (tr -d -)

Because the syntax used inside $( ... ) substitution is exactly the same as in the "main" command line, you also need to use echo to actually produce the variable's contents as output before they can be piped:

NewString=$(echo "$OldString" | tr -d -)

myfunction -w "$(echo "$OldString" | tr -d -)"

That said, there is actually an alternative bash-specific method to pipe just some text without a whole command (although it's not necessarily better; in some cases perhaps even worse):

NewString=$(tr -d - <<< "$OldString")

myfunction -w "$(tr -d - <<< "$OldString")"

But instead of either, you should just use parameter expansion:


myfunction -w "${OldString//-}"
  • This is the correct answer. Specifically, the parameter expansion method should be used. – Guy Gastineau Mar 15 at 15:12
  • Thanks for the quick response @grawity. The first version works, but unfortunately the second two aren't working for me when I try to use them directly. So 'NewString="In-put-St-ring" myfunction -w ${NewString//-}' works, but 'myfunction -w ${"In-put-St-ring"//-}' doesn't work. – Scott Mar 15 at 15:53
  • It only applies to variables, not string literals. But as you've said in the question, you're getting the string from another program, so it'll be a variable anyway... – grawity Mar 15 at 16:24

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.