Qualquer uma das construções de aninhamento que podem ser interpoladas dentro de cadeias de caracteres pode ter outras cadeias dentro delas: elas são analisadas como um novo script, até o marcador de fechamento, e podem até ser aninhadas em vários níveis. Todos, exceto um daqueles, começam com a $
. Todos eles estão documentados em uma combinação do manual do Bash e da especificação da linguagem de comandos do shell POSIX.
Existem alguns casos dessas construções:
Substituição de comando com$( ... )
, como você encontrou. POSIX especifica este comportamento :
Com o $(command)
formulário, todos os caracteres que seguem o parêntese aberto ao parêntese de fechamento correspondente constituem o comando. Qualquer script shell válido pode ser usado para comando ...
As cotações fazem parte de scripts de shell válidos, portanto, são permitidas com seu significado normal.
- Substituição de comando usando
`
também.
O elemento "word" das instâncias avançadas de substituição de parâmetros, como${parameter:-word}
. A definição de "palavra" é :
Uma sequência de caracteres tratados como uma unidade pelo shell
- que inclui texto citado e até citações mistas a"b"c'd'e
- embora o comportamento real das expansões seja um pouco mais liberal do que isso, e por exemplo ${x:-hello world}
também funcione.
Expansão aritmética com $(( ... ))
, embora seja amplamente inútil lá (mas você também pode aninhar substituição de comando ou expansões variáveis, e depois ter aspas úteis dentro delas). O POSIX afirma que :
A expressão deve ser tratada como se estivesse entre aspas duplas, exceto que as aspas duplas dentro da expressão não são tratadas especialmente. O shell deve expandir todos os tokens na expressão para expansão de parâmetro, substituição de comando e remoção de cotação.
portanto, esse comportamento é explicitamente necessário. Isso significa echo "abc $((4 "*" 5))"
aritmética, em vez de globbing.
Observe que a $[ ... ]
expansão aritmética de estilo antigo não é tratada da mesma maneira: as aspas serão um erro se aparecerem, independentemente de a expansão ser citada ou não. Este formulário não está mais documentado e não deve ser usado de qualquer maneira.
- Tradução específica de localidade com
$"..."
, que na verdade usa o "
como elemento principal. $"
é tratado como uma única unidade.
Há um outro caso de aninhamento que você não pode esperar, sem envolver cotações, que é a expansão entre chaves : {a,b{c,d},e}
expande para "a bc bd e". ${x:-a{b,c}d}
faz não ninho, no entanto; é tratado como uma substituição de parâmetro, fornecendo " a{b,c
", seguido de " d}
". Isso também está documentado :
Quando chaves são usadas, a chave final correspondente é o primeiro '}' não escapado por uma barra invertida ou dentro de uma cadeia de caracteres citada, e não dentro de uma expansão aritmética incorporada, substituição de comando ou expansão de parâmetro.
Como regra geral, todas as construções delimitadas analisam seus corpos independentemente do contexto circundante (e as exceções são tratadas como bugs ). Em essência, ao ver $(
o código de substituição de comando, apenas solicita ao analisador que consuma o que pode do corpo como se fosse um novo programa e verifica se o marcador final esperado (um sem escape )
ou ))
ou }
) aparece quando o sub-analisador é executado das coisas que pode consumir.
Se você pensar no funcionamento de um analisador de descida recursiva , isso é apenas uma recursão simples para o caso base. Na verdade, é mais fácil de fazer do que o contrário, quando você tem interpolação de strings. Independentemente da técnica de análise subjacente, as conchas que suportam essas construções fornecem o mesmo resultado.
Você pode aninhar a citação o quanto quiser por meio dessas construções e funcionará conforme o esperado. Nenhum lugar ficará confuso ao ver uma citação no meio; em vez disso, será o início de uma nova string entre aspas no contexto interior.