Quel type d'opération est / # / - dans "$ {my_array [@] / # / -}"?

17

La réponse acceptée pour transformer un tableau en arguments d'une commande? utilise la commande Bash suivante:

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

J'essaie de comprendre /#/-exactement ce que fait la pièce. Malheureusement, je ne sais pas comment l'appeler, j'ai donc du mal à trouver de la documentation. J'ai parcouru la section de la page de manuel de Bash sur les tableaux et quelques sites Web, mais je ne trouve rien.

Justin
la source

Réponses:

24

Il s'agit d'une instance de remplacement de modèle dans l' expansion des paramètres du shell : ${parameter/pattern/replacement}développe ${parameter}, remplaçant la première instance de patternavec replacement. Dans le cadre d'un pattern de ce type, #c'est particulier: il ancre le pattern au début du paramètre. Le résultat final de tout cela est d'étendre toutes les valeurs du my_arraytableau, en ajoutant -à chacune (en remplaçant le motif vide au début de chaque paramètre).

Stephen Kitt
la source
2

Oui, c'est un remplacement de modèle dans l' expansion des paramètres du shell comme:

${parameter/pattern/replacement}

Mais si le premier caractère après le premier /est ou /ou #ou %il a la signification spéciale de all(répété),start et end.

avec:

$ str='one_#two_two_three_one'

Un single /remplacera la première instance. La première instance de one:

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

Ou la première instance de two:

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

L'instance de one à la fin:

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

Toutes les répétitions de two :

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

L'instance de one au début:

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

Une chaîne commençant par #(citez le# ):

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

Mais si vous laissez le # (sans guillemets) seul, le remplacement est défini au début de la variable:

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

De plus, si le paramètre est un tableau, le remplacement se fait sur tous les éléments:

$ str=( one two three )
$ echo "${str[@]/#/==}"
==one ==two ==three
Isaac
la source
Le libellé est un peu trompeur car le #et %font partie du modèle tandis qu'il //est différent de l'opérateur /et utilise les mêmes modèles. Vous pouvez avoir pattern='#x'; echo "${var/$pattern}"(ou ${var//$pattern}), mais ce pattern=/x; echo "${var/$pattern}"n'est pas la même chose que echo "${var//x}". Notez que #et %peut être combiné dans zsh, mais pas dans bashni ksh.
Stéphane Chazelas