Acho que ao escrever texto como entrada para outro programa, quaisquer substituições de comando entre aspas duplas no texto pretendido são interpretadas e expandidas pelo shell
Os links na resposta aqui afirmam que aspas simples podem ser usadas para evitar a expansão de parâmetros ou a substituição de comandos. No entanto, estou descobrindo que colocar uma substituição de comando entre aspas simples também falha em impedir que o shell expanda a substituição de comando
Como você evita que o shell interprete as substituições de comando que são destinadas a texto em vez de um comando a ser executado?
Uma demonstração
$ echo "`wc -l *`"
tenta contar linhas em todos os arquivos no diretório atual
$ echo "'`wc -l *`'"
Mesmo resultado, ou seja, conta linhas em todos os arquivos no diretório atual
atualização A partir desta demonstração, percebi que o problema parece ser que estou citando as aspas simples. Acho que colocar aspas simples e `
(backtick) entre aspas duplas preserva o significado literal de (ou seja, suprime) as aspas simples, mas não preserva o significado literal da backquote (ou seja, backtick) que introduz a substituição do comando.
No meu caso de uso, a entrada para outro comando precisa ser citada. Com este documento dizendo que:
Uma aspa simples não pode ocorrer entre aspas simples
Como você evita que uma substituição de comando entre aspas simples seja expandida quando a substituição de comando entre aspas simples está dentro de uma string entre aspas (duplas)? Deve haver uma maneira de fazer isso além de usar escapes de barra invertida
Situação atual
Em um programa que estou usando, a única maneira de dividir a descrição de uma tarefa em linhas separadas é colocar a descrição entre aspas duplas:
$ task add "first line doesn\'t say much
Second line says a lot but part of this line does not appear in the resulting description 'truncate -s0 !(temp_file | temp_dir)' truncates all files to 0 bytes as shown by: '`wc -l *`'"
A descrição resultante:
first line doesn\ -s0 !(temp_file | temp_dir)' truncates all files to 0 bytes as shown by: 0 file1 10 file2 0 directory1 0 directory2 502 file3 123 file4 162 file5 0 directory3
Como você pode ver
't say much
Second line says a lot but part of this line does not appear in the resulting description 'truncate
está faltando na descrição e o shell interpretou 'wc -l *'
como uma substituição de comando, incluindo assim as contagens de linha de todos os arquivos no diretório atual como parte da descrição
O que está fazendo com que o shell remova a parte do argumento task
entre \
(barra invertida) e -s
, e como você evita que o shell interprete a substituição de comando entre aspas simples (ie '`wc -l *`'
)?
Use citações fortes com aspas simples:
E se você também quiser incluir aspas simples nesse argumento passado para
printf
, precisará usar aspas diferentes para'
si mesmo, como:Ou:
Outras alternativas incluem escapar da
`
barra invertida entre aspas duplas:Ou ter
`
sido o resultado de alguma expansão:Observe também:
para produzir texto arbitrário sem ter que se preocupar em citar (observe as aspas ao redor do primeiro
EOF
).Você também pode fazer:
Que com
ksh93
oumksh
você pode otimizar para:(também funciona em
zsh
, mas ainda é executadocat
em um subshell) para$var
conter literalmenteecho '`wc -l *`'
.No
fish
shell, você pode incorporar'
com :'...'
\'
mas de qualquer forma
`
não é especial lá, então:funcionaria também.
Em rc, es ou
zsh -o rcquotes
, você pode inserir um'
dentro'...'
com''
:Consulte Como usar um caractere especial como um normal? para mais detalhes.
Aqui (quebras de linha adicionadas),
a string inteira está entre aspas duplas, então substituições de comandos e outras expansões serão executadas lá. Isso acontece no shell, antes de
task
ver essa string, e você precisará evitá-lo com barras invertidas ou colocando essa parte entre aspas simples.Por exemplo
Então,
passaria a string
...shown by: '`wc -l *`'
paratask
. Cabe a ele o que fazer com isso.Se você não quiser usar barras invertidas, aqui está a maneira de colocá-lo entre aspas simples:
(O
a
's marca as partes com aspas duplas, oB
's as partes com aspas simples. Eles são apenas concatenados na linha de comando do shell. As aspas simples literais estão dentro das strings com aspas duplas.)Quanto às aspas simples e à barra invertida, você não precisa escapar uma aspa simples entre aspas duplas e, na verdade, a barra invertida permanecerá lá:
Pelo que você mostra, parece que
task
remove pelo menos a primeira string entre aspas simples do argumento (mais uma palavra depois disso, já que a parte removida foi't say much ... 'truncate
)O shell não fará isso, isso funciona bem:
É altamente provável que não seja o shell fazendo isso.
Não é aspas simples, é aspas duplas com aspas simples ao lado.
Você pode escapar dos acentos graves usando uma barra invertida, conforme mostrado abaixo:
Para escapar de qualquer sequência de caracteres arbitrária para que nenhum caractere especial seja processado e nenhuma substituição seja feita:
'
por'\''
Por exemplo:
Torna-se
Observe se a string começa ou termina com
'
, você termina com''
o início/fim, que não faz nada e pode ser removido, mas é válido deixá-la lá (por exemplo, para manter uma função de escape de string simples).