What type of operation is /#/- in "${my_array[@]/#/-}"?

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

Tags:

Bash

Array