Uma resposta StackOverflow com mais de 3,5 mil votos apresenta este recurso para atribuir ao DIR
diretório do script bash atual:
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
Estou intrigado com as aspas duplas aninhadas. Tanto quanto posso dizer, os seguintes fragmentos são citados duas vezes:
"$( cd "
"${BASH_SOURCE[0]}"
" && pwd )"
... e tudo o mais à direita do =
(ie $( dirname
e )
) não é citado. Em outras palavras, suponho que os caracteres 2, 4 e 6 "
fechem os caracteres 1, 3 e 5 "
, respectivamente.
Entendo o que as aspas duplas "${BASH_SOURCE[0]}"
alcançam, mas qual é o objetivo dos outros dois pares de aspas duplas?
Se, por outro lado (e não obstante a alta pontuação dos votos), o trecho acima estiver incorreto, qual é o caminho certo para atingir sua intenção nominal?
(Por intenção nominal, quero dizer: colete o valor retornado pwd
depois de first cd
-ing no diretório retornado por dirname "${BASH_SOURCE[0]}"
e faça cd
-ing em um sub shell, para que o $PWD
shell pai permaneça inalterado).
$( here, it's a subshell, but you are writing code as if you were writing it on the "first level" of the shell .... )
.lsb_dist="$(. /etc/os-release && echo "$ID")"; echo "$lsb_dist"
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
funciona.Respostas:
Seu quebra-cabeça não está certo sobre como
bash
(e o shell em geral) analisou a entrada. Em:Primeiro,
bash
analise o lado direito da atribuição em uma sequência longa,$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
pois aspas duplas podem aparecer dentro de aspas duplas .Depois disso,
bash
comece a analisar a substituição do comando. Como todos os caracteres que seguem parênteses abertos a parênteses anexos são usados para construir o comando dentro da substituição de comando, você obterá:O shell continua analisando esse comando composto, divida-o em duas partes:
cd "$( dirname "${BASH_SOURCE[0]}" )"
Em seguida, aplicando a mesma regra de análise para
cd "$( dirname "${BASH_SOURCE[0]}" )"
, mas desta vez, aspas duplas não são redundantes, mas fazem sentido. Eles impedem a divisão do campo no resultado de$( dirname "${BASH_SOURCE[0]}" )
, e também a expansão de${BASH_SOURCE[0]}
(Em contraste com as aspas duplas mais externas, não é necessário no RHS da atribuição de variáveis para impedirsplit+glob
).Esta regra se aplica à substituição de comandos em todos os shell POSIX . Um quebra-cabeça com mais detalhes você pode ler na seção Reconhecimento de token da especificação POSIX .
fonte
Uma vez dentro
$(...)
, as citações começam do zero.Em outras palavras,
"..."
e$(...)
podem aninhar um dentro do outro. A substituição do processo,,$(...)
pode conter uma ou mais seqüências completas de aspas duplas. Além disso, cadeias de caracteres com aspas duplas podem conter uma ou mais substituições de processo completas . Mas eles não se entrelaçam. Portanto, uma string de aspas duplas que inicia dentro de uma substituição de processo nunca se estende para fora dela ou vice-versa.Então, considere:
Dentro do interior
$(...)
é:No acima
${BASH_SOURCE[0]}
é citado duplo. Quaisquer aspas, duplas ou simples, fora da$(...)
são irrelevantes ao determinar que${BASH_SOURCE[0]}
são aspas duplas.O exterior
$(...)
contém:Aqui, a expressão
$( dirname "${BASH_SOURCE[0]}" )
está entre aspas duplas. O fato de haver aspas fora do exterior$(...)
é irrelevante quando se considera o que está dentro dele. O fato de existirem aspas no interior$(...)
também é irrelevante.Aqui está como as aspas duplas coincidem:
fonte
irrelevant
? Exceto pela maioria dos parênteses externos, todos os outros têm seu próprio significado.$(...)
se prende mais do que"..."
" não faz sentido. Eles não são operadores infix, e não há hierarquia entre eles (se houvesse, isso significaria que as aspas não podem estar entre parênteses ou parênteses não podem estar entre aspas, mas esse não é o caso). O termo técnico é isso$(…)
e"…"
ninho.