Eu tenho uma matriz de "opções" de um comando.
my_array=(option1 option2 option3)
Eu quero chamar esse comando em um script bash, usando os valores da matriz como opções. Então, command $(some magic here with my_array) "$1"
torna-se:
command -option1 -option2 -option3 "$1"
Como eu posso fazer isso? É possível?
-
ao início de cada palavramy_array
?Respostas:
Eu preferiria uma
bash
maneira simples :Uma razão para isso são os espaços. Por exemplo, se você tiver:
As
sed
soluções baseadas o transformarão em-option1 -option2 -with -space -option3
(comprimento 5), mas abash
expansão acima o transformará em-option1 -option2 with space -option3
(comprimento ainda 3). Raramente, mas às vezes isso é importante, por exemplo:fonte
somevar=("${my_array[@]/#/-}")
(Nota do parêntese em torno do valor). Então é claro que você tem que manter a manuseá-lo como uma matriz quando usá-lo:echo "${somevar[@]}"
. Em relação às funções, você está muito limitado pelas possibilidades da linguagem. Você pode passar um array:somefunc "${my_array[@]/#/-}"
, em seguida, dentro de você vai tê-lo em$@
:function somefunc() { echo "$@"; }
. Mas o mesmo$@
conterá os outros parâmetros também, se existir, e não há outra maneira de retornar a matriz modificada que stdout.@
como subscrito de matriz? Eu testei com o zsh 5.5.1 e a única diferença que notei foi que o zsh prefixou cada item apenas quando escrito como${my_array[@]/#/-}
, enquanto o bash também o fez por*
subscrito.Não processei que estava em uma matriz e estava pensando em espaço em branco separado em uma string. Esta solução funcionará com isso, mas, como é uma matriz, siga a solução do manatwork (
@{my_array[@]/#/-}
).Isso não é tão ruim com
sed
um subshell. A facilidade de regex depende do que você pode garantir sobre as opções. Se as opções forem todas uma "palavra" (a-zA-Z0-9
apenas), um limite simples da palavra inicial (\<
) será suficiente:Se suas opções tiverem outros caracteres (provavelmente
-
), você precisará de algo um pouco mais complexo:^
corresponde ao início da linha,[ \t]
corresponde a um espaço ou tabulação,\|
corresponde a um dos lados (^
ou[ \t]
),\(
\)
agrupa (para\|
) e armazena o resultado,\<
corresponde ao início de uma palavra.\1
inicia a substituição mantendo a primeira partida entre parens (\(\)
) e,-
claro, adiciona o traço que precisamos.Estes funcionam com o gnu sed, se não funcionarem com o seu, me avise.
E se você usar a mesma coisa várias vezes, é possível calculá-lo apenas uma vez e armazená-lo:
fonte
gsed
(instalei usandohomebrew
). Outra coisa: em vez deecho $my_array
, eu precisava fazerecho ${my_array[@]}
para obter todos os itensmy_array
:echo $my_array
estava me dando apenas o primeiro elemento. Mas obrigado pela resposta e pela explicação da regex, especialmente sobre "limite de palavras", isso é extremamente útil. :)[ $(echo x | sed 's/\</y/') == "yx" ] || exit
.fonte