The accepted answer to Transform an array into arguments of a command? uses the following Bash command:

command "${my_array[@]/#/-}" "$1"

I'm trying to figure out what the /#/- part does, exactly. Unfortunately, I don't know what to call it, so I'm having trouble finding any documentation. I've looked through the Bash man page section on arrays and a few websites, but can't find anything.

up vote 24 down vote accepted

This is an instance of pattern replacement in shell parameter expansion: ${parameter/pattern/replacement} expands ${parameter}, replacing the first instance of pattern with replacement. In the context of a pattern of this kind, # is special: it anchors the pattern to the start of the parameter. The end result of all this is to expand all the values in the my_array array, prepending - to each one (by replacing the empty pattern at the start of each parameter).

Yes, it is a pattern replacement in shell parameter expansion as:

${parameter/pattern/replacement}

But if the first character after the first / is either / or # or % it has the special meaning of all (repeated), start and end.

with:

$ str='one_#two_two_three_one'

A single / will replace the first instance. The first instance of one:

$ echo "${str/one/x-x}"
x-x_#two_two_three_one

Or the first instance of two:

$ echo "${str/two/x-x}"
one_#x-x_two_three_one

The instance of one at the end:

$ echo "${str/%one/x-x}"
one_#two_two_three_x-x

All repetitions of two:

$ echo "${str//two/x-x}"
one_#x-x_x-x_three_one

The instance of one at the start:

$ echo "${str/#one/x-x}"
x-x_#two_two_three_one

An string that start with # (quote the #):

$ echo "${str/\#two/x-x}"
one_x-x_two_three_one

But if you leave the # (unquoted) alone, the replacement is set at the beginning of the variable:

$ echo "${str/#/====}"
====one_#two_two_three_one

Furthermore, if the parameter is an array, the replacement is done on all elements:

$ str=( one two three )
$ echo "${str[@]/#/==}"
==one ==two ==three
  • The wording is a bit misleading as the # and % are part of the pattern while // is a different operator from / and use the same patterns. You can have pattern='#x'; echo "${var/$pattern}" (or ${var//$pattern}), but pattern=/x; echo "${var/$pattern}" is not the same as echo "${var//x}". Note that # and % can be combined in zsh, but not bash nor ksh. – Stéphane Chazelas Oct 6 at 22:23

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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