Existe alguma lista abrangente de caracteres que precisam ser escapados no Bash? Pode ser verificado apenas com sed
?
Em particular, eu estava verificando se é %
necessário escapar ou não. eu tentei
echo "h%h" | sed 's/%/i/g'
e funcionou bem, sem escapar %
. Isso significa %
que não precisa ser escapado? Essa foi uma boa maneira de verificar a necessidade?
E mais geral: eles são os mesmos personagens para escapar shell
e bash
?
Respostas:
Existem duas regras fáceis e seguras que funcionam não apenas
sh
como tambémbash
.1. Coloque a string inteira entre aspas simples
Isso funciona para todos os caracteres, exceto as aspas simples. Para escapar da aspas simples, feche as aspas antes dela, insira a aspas simples e reabra a aspas.
comando sed:
sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"
2. Escape de todos os caracteres com uma barra invertida
Isso funciona para todos os caracteres, exceto nova linha. Para caracteres de nova linha, use aspas simples ou duplas. As strings vazias ainda devem ser manuseadas - substitua por
""
comando sed:
sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.2b. Versão mais legível do 2
Há um conjunto fácil de caracteres seguro, como
[a-zA-Z0-9,._+:@%/-]
, que pode ser deixado sem escape para mantê-lo mais legívelcomando sed:
LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.Observe que em um programa sed, não se pode saber se a última linha de entrada termina com um byte de nova linha (exceto quando está vazio). É por isso que ambos os comandos sed acima assumem que não. Você pode adicionar uma nova linha entre aspas manualmente.
Observe que variáveis de shell são definidas apenas para texto no sentido POSIX. O processamento de dados binários não está definido. Para as implementações importantes, o binário funciona com exceção de bytes NUL (porque as variáveis são implementadas com cadeias C e devem ser usadas como cadeias C, ou seja, argumentos de programa), mas você deve alternar para um código de idioma "binário", como latin1 .
(Você pode validar facilmente as regras lendo a especificação POSIX para
sh
. Para o bash, consulte o manual de referência vinculado por @AustinPhillips)fonte
sed
, mas exigebash
.formato que pode ser reutilizado como entrada do shell
Existe uma diretiva de formato especial
printf
(%q
) criada para este tipo de solicitação:Algumas amostras:
Isso também pode ser usado através de variáveis:
Verificação rápida com todos os (128) bytes ascii:
Observe que todos os bytes de 128 a 255 precisam ser escapados.
Isso deve render algo como:
Onde o primeiro campo é o valor hexa do byte, o segundo contém
E
se o caractere precisa ser escapado e o terceiro campo mostra a apresentação do caractere escapado.Por que
,
?Você pode ver alguns caracteres que nem sempre precisam ser escapados, como
,
,}
e{
.Então nem sempre, mas em algum momento :
ou
mas cuidado:
fonte
subprocess.Popen(['bash', '-c', 'printf "%q\0" "$@"', '_', arbitrary_string], stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()
você fornecerá uma versão do shell com aspas apropriadasarbitrary_string
.%q
foi quebrado por um longo tempo - Se minha mente me serve bem, um erro foi corrigido (mas ainda pode ser quebrado) em 2013, depois de ser quebrado por ~ 10 anos. Portanto, não confie nisso.shlex.quote()
(> = 3.3,pipes.quote()
- não documentado - para versões mais antigas) também fará o trabalho e produzirá uma versão mais legível por humanos (adicionando aspas e escapando, conforme necessário) da maioria das strings, sem a necessidade de gerar uma concha.,
. Fiquei surpreso ao saber que o Bash embutidoprintf -- %q ','
dá\,
, mas/usr/bin/printf -- %q ','
dá,
(não escapou). Mesmo para outros caracteres:{
,|
,}
,~
.Para evitar que outra pessoa precise RTFM ... no bash :
... então, se você escapar desses (e da própria citação, é claro), provavelmente estará bem.
Se você adotar uma abordagem mais conservadora 'em caso de dúvida, escape', deve ser possível evitar obter caracteres com significado especial, não escapando aos caracteres identificadores (ou seja, letras ASCII, números ou '_'). É muito improvável que eles tenham um significado especial e, portanto, precisem ser escapados.
fonte
Usando a
print '%q'
técnica , podemos executar um loop para descobrir quais caracteres são especiais:Dá esta saída:
Alguns dos resultados, como
,
parecem um pouco suspeitos. Seria interessante obter as contribuições de @ CharlesDuffy sobre isso.fonte
,
parecer um pouco desconfiado no último parágrafo da minha resposta%q
não sabe em que parte do shell você planeja usar o personagem; portanto, ele escapará de todos os caracteres que podem ter um significado especial em qualquer contexto possível do shell.,
ela mesma não tem significado especial para ela, mas como @ F.Hauri apontou em sua resposta, ela tem um significado especial na{...}
expansão de chaves: gnu.org/savannah-checkouts/gnu/bash/manual/… É assim! o que também requer expansão apenas em situações específicas, não em geral:echo Hello World!
funciona muito bem, masecho test!test
falha.Os caracteres que precisam ser escapados são diferentes no shell Bourne ou POSIX e no Bash. Geralmente (muito) o Bash é um superconjunto dessas conchas; portanto, tudo o que você escapar
shell
deve escapar no Bash.Uma boa regra geral seria "em caso de dúvida, escape". Mas escapar de alguns personagens lhes dá um significado especial, como
\n
. Eles estão listados nasman bash
páginas emQuoting
eecho
.Fora isso, escape de qualquer caractere que não seja alfanumérico; é mais seguro. Não conheço uma única lista definitiva.
As páginas de manual listam todas elas em algum lugar, mas não em um só lugar. Aprenda o idioma, esse é o caminho para ter certeza.
Um que me chamou a atenção é
!
. Este é um caractere especial (expansão do histórico) no Bash (e csh), mas não no shell Korn. Atéecho "Hello world!"
dá problemas. Usar aspas simples, como sempre, remove o significado especial.fonte
sed
é bom o suficiente para ver se precisa escapar. Obrigado pela sua resposta!sed
Não é necessário verificar com, você pode verificar com quase tudo.sed
não é o problema,bash
é. Dentro de aspas simples, não há caracteres especiais (exceto aspas simples), você não pode nem mesmo escapar caracteres lá. Umsed
comando geralmente deve estar entre aspas simples, porque os metacaracteres do RE têm muitas sobreposições com os metacaracteres do shell para serem seguros. A exceção é ao incorporar variáveis de shell, o que deve ser feito com cuidado.echo
. Se você conseguir o que colocar, ele não precisará ser escapado. :)Presumo que você esteja falando sobre strings do bash. Existem diferentes tipos de strings que possuem um conjunto diferente de requisitos para escapar. por exemplo. As strings de aspas simples são diferentes das strings de aspas duplas.
A melhor referência é a citação seção do manual bash.
Explica quais caracteres precisam ser escapados. Observe que alguns caracteres podem precisar ser escapados, dependendo de quais opções estão ativadas, como a expansão do histórico.
fonte
Notei que o bash escapa automaticamente alguns caracteres ao usar o preenchimento automático.
Por exemplo, se você tiver um diretório chamado
dir:A
, o bash será concluído automaticamente paradir\:A
Usando isso, realizei algumas experiências usando caracteres da tabela ASCII e derivou as seguintes listas:
Caracteres que o bash escapa ao concluir automaticamente : (inclui espaço)
Personagens que o bash não escapa :
(Excluí
/
, pois não pode ser usado em nomes de diretório)fonte
printf %q
são modificados e não modificados se passados como argumento - idealmente, percorrendo todo o conjunto de caracteres.