Que tipo de operação é / # / - em "$ {my_array [@] / # / -}"?

17

A resposta aceita para transformar uma matriz em argumentos de um comando? usa o seguinte comando Bash:

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

Estou tentando descobrir exatamente o que a /#/-peça faz. Infelizmente, não sei como chamá-lo, por isso estou tendo problemas para encontrar qualquer documentação. Examinei a seção da página de manual do Bash em matrizes e em alguns sites, mas não consigo encontrar nada.

Justin
fonte

Respostas:

24

Esta é uma instância de substituição de padrão na expansão de parâmetros do shell : ${parameter/pattern/replacement}expande ${parameter}, substituindo a primeira instância de patternwith replacement. No contexto de um padrão desse tipo, #é especial: ancora o padrão no início do parâmetro. O resultado final de tudo isso é expandir todos os valores da my_arraymatriz, precedendo -cada um (substituindo o padrão vazio no início de cada parâmetro).

Stephen Kitt
fonte
2

Sim, é uma substituição de padrão na expansão de parâmetros do shell como:

${parameter/pattern/replacement}

Mas se o primeiro caractere após o primeiro /for /ou #ou %tiver o significado especial de all(repetido) starte end.

com:

$ str='one_#two_two_three_one'

Um único /substituirá a primeira instância. A primeira instância de one:

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

Ou a primeira instância de two:

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

A instância de oneno final:

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

Todas as repetições de two:

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

A instância de oneno início:

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

Uma sequência que começa com #(aspas #):

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

Mas se você deixar o # (não citado) sozinho, a substituição será configurada no início da variável:

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

Além disso, se o parâmetro for uma matriz, a substituição será feita em todos os elementos:

$ str=( one two three )
$ echo "${str[@]/#/==}"
==one ==two ==three
Isaac
fonte
O texto é um pouco enganador, como o #e %fazem parte do padrão, enquanto //é um operador diferente /e usar os mesmos padrões. Você pode ter pattern='#x'; echo "${var/$pattern}"(ou ${var//$pattern}), mas pattern=/x; echo "${var/$pattern}"não é o mesmo que echo "${var//x}". Observe que #e %pode ser combinado zsh, mas não bashnem ksh.
Stéphane Chazelas