Concatenação de string bash usada para criar lista de parâmetros


12

Dado este pedaço de bash:

PARMS='-rvu'
PARMS+=" --delete --exclude='.git'"
echo $PARMS
rsync ${PARMS} . ${TARGET}

O eco mostra a sequência de PARMS conforme o esperado, nenhum erro é exibido, mas o rsync age silenciosamente como se as opções adicionadas pelo + = não existissem. No entanto, isso funciona conforme o esperado:

PARMS='-rvu'
rsync ${PARMS} --delete --exclude='.git' . ${TARGET}

Eu acho que estraguei algo com aspas bash (sempre tive problemas com elas), mas não sei exatamente o que e por que as opções são ignoradas, mesmo que a string pareça ter sido criada corretamente.


1
echo "$PARMS"e rsync "${PARMS}"...
jasonwryan 28/08

Isso funciona para mim com a bashversão 4.2.25 sem nenhuma alteração.
Anthon

Respostas:


17

Há uma diferença entre:

PARMS+="... --exclude='.git'"

e

... --exclude='.git'

Na primeira, as aspas simples estão entre aspas, e estão literalmente presentes no texto substituído, dado rsynccomo argumento. rsyncobtém um argumento cujo valor é --exclude='.git'. No segundo, as aspas simples são interpretadas pelo shell no momento em que são escritas, porque elas não estão entre aspas e rsyncconseguem ver --exclude=.git.

Nesse caso, você não precisa de aspas simples - .gité uma palavra shell perfeitamente válida por si só, sem caracteres especiais, para que você possa usá-la literalmente no comando.

Melhor para esse tipo de coisa, porém, é uma matriz :

PARMS=(-rvu)
PARMS+=(--delete --exclude='.git')
rsync "${PARMS[@]}"

Isso cria seu comando como palavras separadas, com qualquer citação que você deseja interpretar no momento em que escreve a linha da matriz. "${PARMS[@]}"expande para cada entrada na matriz como um argumento separado, mesmo que o argumento em si tenha caracteres ou espaços especiais, para rsyncque ele veja o que você escreveu como pretendia.


bashexecutou a divisão da palavra após ter ${PARMS}sido expandida. Portanto, as aspas simples também foram interpretadas pelo shell.
cuonglm

2
Tente! Eu fiz. As aspas permanecem e, se houver espaços entre eles, eles são pontos de divisão de qualquer maneira.
22714 Michael Homer

@Gnouc: A partir da página man bash: "Citar Remoção: Após as expansões anteriores, todas as ocorrências não cotadas dos personagens \ , 'e ". Que não resultou de uma das expansões acima são removidas" "expansões acima" inclui expansão de parâmetro que realiza a expansão de ${PARMS}.
CAMH

Obrigado. Portanto, entendo que, nesse caso, omitir as aspas simples entre as duplas funcionará, mas por uma questão de exaustividade - e se eu precisasse citar alguns caracteres especiais e não quisesse usar sua última abordagem?
Neuviemeporte 28/08

Se seus caracteres especiais não fazem parte IFS(geralmente de espaço em branco), você não precisa citá-los. Se estiverem, você não terá sorte, a menos que hackear algo junto eval- isso é um pouco incorreto em geral, e as matrizes são a maneira certa de lidar com isso.
28814 Michael Homer

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.