Jakiego rodzaju operacją jest / # / - w „$ {my_array [@] / # / -}”?

17

Akceptowana odpowiedź na przekształcenie tablicy w argumenty polecenia? używa następującego polecenia Bash:

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

Staram się dowiedzieć, co /#/-dokładnie robi ta część. Niestety nie wiem, jak to nazwać, więc mam problem ze znalezieniem dokumentacji. Przejrzałem sekcję strony podręcznika Bash na temat tablic i kilku stron internetowych, ale nic nie mogę znaleźć.

Justin
źródło

Odpowiedzi:

24

Jest to przypadek wymiany wzór w muszli rozszerzalności parametrów : ${parameter/pattern/replacement}rozszerza ${parameter}zastępując pierwszy przykład patternz replacement. W kontekście tego rodzaju wzorca #jest wyjątkowy: zakotwicza wzorzec na początku parametru. Końcowym rezultatem tego wszystkiego jest rozwinięcie wszystkich wartości w my_arraytablicy, poprzedzając -każdą z nich (zastępując pusty wzorzec na początku każdego parametru).

Stephen Kitt
źródło
2

Tak, jest to zamiana wzorca w rozszerzaniu parametrów powłoki, ponieważ:

${parameter/pattern/replacement}

Ale jeśli pierwszy znak po pierwsze /jest albo /albo #albo %ma specjalne znaczenie all(powtórzone), starta end.

z:

$ str='one_#two_two_three_one'

Pojedynczy /zastąpi pierwszą instancję. Pierwsze wystąpienie one:

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

Lub pierwsza instancja two:

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

Wystąpienie onena końcu:

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

Wszystkie powtórzenia two:

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

Wystąpienie onena początku:

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

Ciąg rozpoczynający się od #(cytuj #):

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

Ale jeśli pozostawisz # (niecytowany) w spokoju, zamiana zostanie ustawiona na początku zmiennej:

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

Ponadto, jeśli parametr jest tablicą, zamiana jest wykonywana dla wszystkich elementów:

$ str=( one two three )
$ echo "${str[@]/#/==}"
==one ==two ==three
Izaak
źródło
Sformułowanie jest nieco mylące, ponieważ #i %stanowią część wzorca, podczas gdy //różni się od operatora /i używa tych samych wzorców. Możesz mieć pattern='#x'; echo "${var/$pattern}"(lub ${var//$pattern}), ale pattern=/x; echo "${var/$pattern}"to nie to samo co echo "${var//x}". Zauważ, że #i %można łączyć zsh, ale nie bashani ksh.
Stéphane Chazelas