Shell – How to Replace One Char to Get Many Strings

bashsedshell-script

I can find many questions with answers in the other direction, but unfortunately not in the one I would like to have my replacements: I intend to replace a char, such as #, in a string, such as test#asdf, with a sequence, such as {0..10} to get a sequence of strings, in this example test0asdf test1asdf test2asdf test3asdf test4asdf test5asdf test6asdf test7asdf test8asdf test9asdf test10asdf.

I tried, from others:

  • echo '_#.test' | tr # {0..10} (throws usage)
  • echo '_#.test' | sed -r 's/#/{0..10}/g' (returns _{0..10}.test)
  • echo '_#.test' | sed -r 's/#/'{0..10}'/g' (works for the first, afterwards I get sed: can't read (...) no such file or directory)

What is a working approach to this problem?

Edit, as I may not comment yet: I have to use # in the string, in which this character should be replaced, as the string passed from another program. I could first replace it with another char though.

Best Answer

The {0..10} zsh operator (now also supported by a few other shells including bash) is just another form of csh-style brace expansion.

It is expanded by the shell before calling the command. The command doesn't see those {0..10}.

With tr '#' {0..10} (quoting that # as otherwise it's parsed by the shell as the start of a comment), tr ends being called with ("tr", "#", "0", "1", ..., "10") as arguments and tr doesn't expect that many arguments.

Here, you'd want:

echo '_'{0..10}'.test' 

for echo to be passed "_0.test", "_1.test", ..., "_10.test" as arguments.

Or if you wanted that # to be translated into that {0..10} operator, transform it into shell code to be evaluated:

eval "$(echo 'echo _#.test' | sed 's/#/{0..10}/')"

where eval is being passed echo _{0..10}.test as arguments.

(not that I would recommend doing anything like that).

Related Question