¿Qué tipo de operación es / # / - en “$ {my_array [@] / # / -}”?

17

¿La respuesta aceptada para transformar una matriz en argumentos de un comando? utiliza el siguiente comando Bash:

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

Estoy tratando de averiguar qué /#/-hace exactamente la parte. Desafortunadamente, no sé cómo llamarlo, así que tengo problemas para encontrar documentación. He revisado la sección de la página de manual de Bash sobre matrices y algunos sitios web, pero no puedo encontrar nada.

Justin
fuente

Respuestas:

24

Esta es una instancia de reemplazo de patrón en la expansión de parámetros de shell : se ${parameter/pattern/replacement}expande ${parameter}, reemplazando la primera instancia de patterncon replacement. En el contexto de un patrón de este tipo, #es especial: ancla el patrón al inicio del parámetro. El resultado final de todo esto es expandir todos los valores en la my_arraymatriz, anteponiendo -a cada uno (reemplazando el patrón vacío al comienzo de cada parámetro).

Stephen Kitt
fuente
2

Sí, es un reemplazo de patrón en la expansión de parámetros de shell como:

${parameter/pattern/replacement}

Pero si el primer carácter después de la primera /es o /o #o %tiene el significado especial de all(repetido), starty end.

con:

$ str='one_#two_two_three_one'

Un solo /reemplazará a la primera instancia. La primera instancia de one:

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

O la primera instancia de two:

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

La instancia de oneal final:

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

Todas las repeticiones de two:

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

La instancia de oneal principio:

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

Una cadena que comienza con #(cita el #):

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

Pero si deja solo el # (sin comillas), el reemplazo se establece al comienzo de la variable:

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

Además, si el parámetro es una matriz, el reemplazo se realiza en todos los elementos:

$ str=( one two three )
$ echo "${str[@]/#/==}"
==one ==two ==three
Isaac
fuente
El texto es un poco engañoso como el #y %son parte del patrón, mientras que //es un operador diferente de /y utilizar los mismos patrones. Puede tener pattern='#x'; echo "${var/$pattern}"(o ${var//$pattern}), pero pattern=/x; echo "${var/$pattern}"no es lo mismo que echo "${var//x}". Tenga en cuenta que #y %se puede combinar en zsh, pero no bashni ksh.
Stéphane Chazelas