Como usar um caractere especial como um caractere normal?

13

Muitas perguntas como 'Como digitar o caractere de aspas duplas (")? estão sendo solicitadas e não queremos desorganizar nossa comunidade com a mesma resposta (digite-a como \"se não estivesse em 's, "se em 's.) Portanto, a pergunta está aqui.

Você não pode digitar caracteres especiais em um terminal como os normais, por exemplo, este comando falhará:

echo Updates (11)

Então, como digitar esses caracteres no terminal como se fossem normais?

!#$^&*?[](){}<>~;'"\|<space><tab><newline>
EKons
fonte
Não há shell Unix que eu saiba onde o retorno de carro é especial. =, @E %são especiais em algumas conchas em alguns contextos.
Stéphane Chazelas
@ StéphaneChazelas Umm ... o retorno de carro ( ^M) age como um feed de linha ( ^J) para mim (Ubuntu 14.04, sh).
EKons
Não, suas transformações controlador do terminal ^Mpara ^Jna entrada, mas ^Mnão é especial para o shell e não precisa citado. Digite echo ^V^M | hde você verá o caractere 0d (e o 0a acrescentado por eco).
Stéphane Chazelas
@ StéphaneChazelas Umm ... Eu não sei o que hdé, talvez xxdseja melhor como um visualizador hexadecimal.
EKons
Qualquer que seja. Use POSIX od -tx1ou sed -n lxxd do vim, se você não tiver hd. Alguns sistemas também têm cat -vteoucat -A
Stéphane Chazelas

Respostas:

26

Isso depende muito da concha. Verifique o manual do shell para obter detalhes.

Observe também que alguns caracteres são especiais apenas em alguns contextos. Por exemplo, na maioria dos shells, *e ?são especiais apenas em contextos de lista, em shells POSIX ou semelhantes a csh, ~é especial apenas no início de uma palavra ou após alguns caracteres como :. Mesmo para =nos zsh. Em algumas cascas, [só é especial quando combinada (com algumas restrições) por a ].

Em alguns shells como bashou yash, caracteres especiais como delimitadores de token em branco também variam com o código do idioma.

Os operadores de citação (para remover o significado especial desses caracteres) também variam muito entre os shells.

Conchas semelhantes a Bourne

Um resumo para os shells tipo Bourne (que são conhecidos por serem chamados shem algum sistema ou outro desde os anos 80):

Casca de Bourne

Caracteres especiais:

  • "\'&|;()^`<>$, space, newline e tab são especiais em linhas de comando simples quando não estão entre aspas.
  • #(exceto na versão anterior) é especial no início de uma linha ou após um espaço, aspas ou tabulação sem aspas &|()^<>;`.
  • {e }são especiais apenas porque são palavras-chave do shell (portanto, apenas palavras na posição de comando).
  • *?[são especiais como operadores de globbing, portanto, apenas em contextos de lista. No caso de [, é [...]esse o operador de globbing, que precisa ser citado [ou ]somente para remover o significado especial.
  • =é especial quando em contextos onde é tratado como um operador de atribuição. Ou seja, em um comando simples, para todas as palavras que não seguem um argumento (exceto depois set -k).

Citando operadores

  • \cita todos os caracteres especiais, exceto nova linha ( \<newline>é uma maneira de continuar uma longa linha lógica na próxima linha física , para que a sequência seja removida). Observe que os backticks adicionam complexidade extra, pois \são usados ​​primeiro para escapar do backtick de fechamento e ajudar o analisador. Dentro de aspas duplas, \só pode ser usado para escapar de si próprio ", $e `( \<newline>ainda é uma continuação de linha). Dentro de um documento aqui, o mesmo, exceto ". \é a única maneira de escapar caracteres dentro dos documentos aqui.
  • "..."aspas escapar todos os personagens, mas em si, \, $e `.
  • '...' aspas simples escapam a todos os caracteres, exceto a si próprio.

Cartuchos POSIX

Os shell POSIX se comportam principalmente como o shell Bourne, exceto que:

ksh

como POSIX, exceto que:

  • {string}é especial se a string contém um aspas ,(ou, ..em alguns casos, e com algumas versões).
  • O ksh93 possui um operador de citação especial adicional: $'...'com regras complexas. Esse operador também é encontrada (com algumas variações) em bash, zsh, mkshe FreeBSD e busybox sh.
  • ksh93também possui um $"..."operador de citação que funciona assim, "..."exceto que a string está sujeita à localização (pode ser configurada para ser traduzida para o idioma do usuário). mkshignora o $no $"...".

bash

como ksh93mas:

  • nos códigos de idioma de caracteres de byte único, todos os caracteres em branco (de acordo com o código de idioma) são considerados delimitadores (como espaço ou tabulação). Com efeito, isso significa que você deve citar todos os bytes com o oitavo bit definido, caso eles possam ser um caractere em branco em algum código de idioma.
  • Quando a expansão do histórico do csh é ativada, como em instâncias interativas, !é especial em alguns contextos e nem sempre as aspas duplas. E ^é especial no início de um comando.

zsh

como ksh93mas:

  • mesma nota que para basha expansão do histórico do csh
  • =é especial como o primeiro caractere de uma palavra ( =lsexpande para /bin/ls).
  • {e }também pode abrir e fechar grupos de comandos quando não delimitados (como em {echo text}trabalhos como os de Bourne { echo text;}).
  • exceto [sozinho, [necessidades citadas, mesmo que não sejam fechadas com a ].
  • Com a extendedglobopção ativada, #, ^e ~são englobamento operadores.
  • Com a bracecclopção, {non-empty-string}é especial.
  • $"..." não é suportado.
  • como uma peculiaridade especial, ?não é especial ao seguir um %(mesmo citado ou expandido) no início de uma palavra (para permitir a %?nameespecificação do trabalho)
  • uma rcquotesopção (não ativada por padrão) permite inserir aspas simples como ''dentro de aspas simples à la rc(veja abaixo).

yash

como POSIXexceto isso.

  • todos os caracteres em branco são considerados delimitadores.
  • Com a brace-expandopção, implementa a expansão de chaves no estilo zsh.

Para todos os shells, existem alguns contextos especiais em que a citação funciona de maneira diferente. Já mencionamos aqui documentos e backticks, mas também existem [[...]]no ksh e em alguns outros shells, POSIX $((...)), caseconstruções ...

Observe também que a citação pode ter outros efeitos colaterais quando se trata de expansões (com aspas duplas) ou quando aplicada a delimitadores de documentos aqui. Ele também desativa as palavras reservadas e afeta a expansão do alias.

Sumário

Nos shells tipo Bourne !#$^&*?[(){}<>~;'"`\|=, SPC, TAB, NEWLINE e alguns bytes com o conjunto de 8 bits são ou podem ser especiais (pelo menos em alguns contextos).

Para remover o significado especial para que eles sejam tratados literalmente, use aspas.

Usar:

  • '...' para remover o significado especial de cada caractere:

    printf '%s\n' '\/\/ Those $quoted$ strings are passed literally as
    single arguments (without the enclosing quotes) to `printf`'
  • \ para remover o significado especial de apenas um caractere:

    printf '<%s>\n' foo bar\ baz #comment

    Acima, apenas o caractere de espaço precedido por a \é passado literalmente para printf. Os outros são tratados pelo shell como delimitadores de token.

  • usar "..."para citar personagens enquanto ainda permitindo expansão de parâmetros ( $var, $#, ${foo#bar}...), a expansão aritmética ( $((1+1))também $[1+1]em algumas conchas) e substituição de comando ( $(...)ou a velha forma `...`. Na verdade, na maioria das vezes, você quer colocar essas expansões dentro aspas duplas em qualquer caso.Você pode usar \dentro "..."para remover o significado especial dos caracteres que ainda são especiais (mas apenas eles).
  • se a string contiver 'caracteres, você ainda poderá usar '...'o restante e usar outros mecanismos de cotação que podem citar 'como "'"ou \'ou (quando disponível) $'\'':

    echo 'This is "tricky", isn'\''t it?'
  • Use a $(...)forma moderna de substituição de comando. Use o antigo apenas `...`para compatibilidade com o shell Bourne, ou seja, para um sistema muito antigo e apenas em atribuições de variáveis, como em não use:

    echo "`echo "foo bar"`"

    O que não funciona com o shell Bourne ou as versões AT&T do ksh. Ou:

    echo "`echo \"foo bar\"`"

    Que funcionará com Bourne e AT&T ksh, mas não com yash, mas use:

    var=`echo "foo bar"`; echo "$var"

    que funcionará com todos.

    Também é impossível aninha-los de maneira portável com aspas duplas; portanto, novamente, use variáveis. Também tenha cuidado com o processamento especial de barra invertida:

    var=`printf '%s\n' '\\'`

    Armazenará apenas uma barra invertida dentro $var, porque há um nível extra de processamento de barra invertida (para \, `e $(e também "quando citado, exceto em yash)) dentro das barras de reticulação, para que você precise

    var=`printf '%s\n' '\\\\'`

    ou

    var=`printf '%s\n' '\\\'

    em vez de.

Família Csh

O csh e o tcsh têm uma sintaxe significativamente diferente, embora ainda haja muito em comum com o shell Bourne, pois eles compartilham uma herança comum.

Caracteres especiais:

  • "\'&|;()^`<>$, espaço, nova linha e guia são especiais em todos os lugares quando não estão entre aspas.
  • #(csh é o shell que foi introduzido #como líder do comentário) é especial no início de um script ou após um espaço, guia ou nova linha não citada.
  • *?[ são especiais como operadores de globbing, portanto, em contextos de lista
  • {non-empty-string} é especial (csh é o shell que introduziu a expansão entre chaves).
  • !e ^são especiais como parte da expansão da história (novamente, uma invenção da csh), e as regras de citação são especiais.
  • ~ (expansão til também uma invenção csh) é especial em alguns contextos.

Citando operadores

Eles são os mesmos do shell Bourne, mas o comportamento é diferente. Se o tcsh se comportar como o csh do ponto de vista da sintaxe, você verá que muitas versões do csh têm erros desagradáveis. Obtenha a versão mais recente do tcsh para obter uma versão mais ou menos funcional do csh.

  • \escapa um único caractere, exceto nova linha (o mesmo que para o shell Bourne). É o único operador de cotação que pode escapar !. \<newline>não escapa, mas o transforma de um separador de comandos em um separador de token (como espaço)
  • "..."escapa todos os personagens exceto o próprio, $, `, nova linha e !. Ao contrário do shell Bourne, você não pode usar \para escapar $e `entrar por dentro "...", mas pode usar \para escapar !ou nova linha (mas não ela mesma, exceto quando antes de uma !ou nova linha). Um literal !é "\!"e um literal \!é "\\!".
  • '...' escapa a todos os caracteres, exceto a si próprio !e a nova linha. Como nas aspas duplas, a !nova linha pode ser escapada com barra invertida.
  • a substituição de comando é somente via `...`sintaxe e dificilmente pode ser usada com segurança.
  • a substituição de variáveis ​​também é mal projetada e propensa a erros. Um $var:qoperador ajuda a escrever um código mais confiável envolvendo variáveis.

Sumário

Fique longe do csh, se puder. Se você não pode usar:

  • aspas simples para citar a maioria dos caracteres. !e nova linha ainda precisa de um \.
  • \ pode escapar da maioria dos personagens
  • "..."pode permitir algumas expansões dentro dele, mas isso é bastante problemático se incorporarem caracteres de nova linha e / ou barra invertida; o melhor é usar apenas aspas simples e $var:qpara expansão variável. Você precisará usar loops se desejar unir elementos de uma matriz de maneira confiável.

rc família

rcé o plan9shell e como seus descendentes ese akangafoi portado para Unix e unix-likes. É um shell com uma sintaxe muito mais limpa e melhor e o que todo mundo usaria se não fôssemos presos a shells tipo Bourne para compatibilidade com versões anteriores.

rc/akanga

Caracteres especiais

  • #;&|^$=`'{}()<>, SPC, TAB e NEWLINE são sempre especiais quando não estão entre aspas.
  • *?[ são operadores de globbing.

Operador de cotação

'...'é o único operador de cotação. A Litteral 'é escrito com ''dentro de aspas simples como em:

 echo 'it''s so simple isn''t it?'

es

espode ser visto como um shell experimental baseado em rc.

No entanto, existem algumas diferenças. O que interessa a esta Q / A é que \também é um operador de citação (que cita todos os caracteres especiais, exceto nova linha) e também pode ser usado para introduzir sequências de escape como \npara nova linha, \bpara barra invertida ...

peixe

fish é um recém-chegado relativo (por volta de 2005), destina-se principalmente ao uso interativo e também possui uma sintaxe significativamente diferente de outras conchas.

caracteres especiais

  • "'\()$%{}^<>;&|sempre especial quando não citado (observe %(para expansão pid) como uma diferença significativa de outras conchas e `não é especial)
  • # (comentário) especial ao seguir espaço sem aspas, tabulação, nova linha ou ;&|^<>
  • *?[...]operadores de globbing (mas não )

Citando operadores

  • \cita um único caractere especial, exceto nova linha, mas cuidado, ele também funciona como um introdutor de sequência de escape C ( \n, \b...). IOW, \nnão é uma citação, nmas uma nova linha.
  • "..."cita tudo, menos ele próprio, $e a barra invertida e a barra invertida podem ser usadas para escapar deles. \<newline>é uma continuação de linha (removida) dentro "...".
  • '...'cita tudo, menos ele próprio e \, e você pode usar barra invertida para escapar deles.
Stéphane Chazelas
fonte
Eu incluí apenas os especiais em todos os contextos (para que cfuncionem da mesma forma \c, cnão sejam c: command not foundexibidos no STDERR, etc.) E eu estou falando shaqui. Além disso, lembre-se de que esta é uma pergunta de "limpeza", ou seja, está aqui para cobrir todos esses personagens, portanto não será necessário fazer mais de 19 perguntas. A pergunta foi postada graças a um incidente em que perguntas diferentes são feitas para diferentes personagens, certamente queremos limpar aqui!
EKons
Bem, ?[são operadores globbing, mas não são especiais em todos os contextos, mas *parecem ser, porque estão echo *mal echoo conteúdo do diretório atual (não escapando a nada). echo ?ecoa um literal ?e echo [ecoa um literal [. Além disso, ]é um oberator globbing também.
EKons
1
@ ΈρικΚωνσταντόπουλος, à *medida que a glob se expande para todos os arquivos ?não ocultos, [a-z]para arquivos de caractere único não ocultos, para arquivos cujo nome é um caractere único entre a e z e assim por diante. Quando eles não correspondem a nenhum arquivo (como no seu caso ?), dependendo do shell, você recebe um erro de não correspondência ou o padrão se expande. Em qualquer caso, mesmo em shell onde eles se expandir para si mesmos, eles precisam citado no caso de eles podem corresponder a um arquivo.
Stéphane Chazelas
Mas, não como um globo, *ainda se expande para algo.
EKons
@ ΈρικΚωνσταντόπουλος, *é como ?, se não corresponder (apenas no caso *, é quando há apenas arquivos ocultos no diretório atual, pois a*é onde não há nenhum arquivo cujo nome comece com a...), ele se expande para em si (mais Bourne-como conchas), ou gera um erro no-jogo ( csh, tcsh, fish(aviso), zsh, bash -O failglob, primeiros conchas Unix), (ou se expande para nada com a opção nullglob de algumas conchas ou se há outro padrão que se expande para algo em csh, tcsh, zsh -o cshnullglob, shells iniciais do unix).
Stéphane Chazelas
4

1. Fuga

Escape de todos esses caracteres com a \, como este (não funciona em novas linhas / retornos de carro):

$ echo Use a \"\\\" symbol to escape characters.
Use a "\" symbol to escape characters.

2. Citação dupla

Coloque o texto inteiro em "s, assim:

$ var=variables;echo "Enclose text in \"s. You can also use $var in them. `echo Surprise!!!`"
Enclose text in "s. You can also use variables in them. Surprise!!!

3. aspas simples

O mesmo que aspas duplas, mas não há token especial.

$ proof=proveit;echo 'This should not read "proveit": $proof'
This should not read "proveit": $proof
EKons
fonte
1
Você está descrevendo o comportamento do fishshell, e não dos shell Bourne, onde a aspas simples cita todos os caracteres (a barra invertida não é especial no interior '...'). Observe que em fish, %também é um caractere especial.
Stéphane Chazelas
@ StéphaneChazelas Não sei como fishfunciona, mas minha experiência é que, em sh, echo '\\'ecos \ e echo '\''ecos '.
EKons
1
echo '\\'\ outputs porque você echoexpande seqüências de escape ANSI C (algumas echoimplementações precisam echo -e '\\'disso). printf '%s\n' '\\'saídas \\.
Stéphane Chazelas
Observe que shnão identifica um shell específico, existem e já foram chamados muitos shells diferentes e geralmente incompatíveis sh.
Stéphane Chazelas
@ StéphaneChazelas Oh ok, vou mudar isso agora. A propósito, existe \'um token especial em uma sequência de caracteres entre aspas simples?
EKons