Digamos que você tenha um Bash alias
como:
alias rxvt='urxvt'
o que funciona bem
Contudo:
alias rxvt='urxvt -fg '#111111' -bg '#111111''
não funcionará e nem:
alias rxvt='urxvt -fg \'#111111\' -bg \'#111111\''
Então, como você acaba combinando as aspas de abertura e fechamento dentro de uma string depois de ter escapado das aspas?
alias rxvt='urxvt -fg'\''#111111'\'' -bg '\''#111111'\''
parece desajeitado, embora represente a mesma string se você puder concatená-las dessa maneira.
"\""
portanto, essas devem ser usadas preferencialmente à resposta de @ liori sempre que possível.Respostas:
Se você realmente deseja usar aspas simples na camada mais externa, lembre-se de colar os dois tipos de cotação. Exemplo:
Explicação de como
'"'"'
é interpretado como justo'
:'
Finalize a primeira cotação que usa aspas simples."
Inicie a segunda cotação, usando aspas duplas.'
Caractere citado."
Finalize a segunda cotação, usando aspas duplas.'
Inicie a terceira cotação, usando aspas simples.Se você não colocar espaços em branco entre (1) e (2) ou entre (4) e (5), o shell interpretará essa sequência como uma palavra longa.
fonte
alias splitpath='echo $PATH | awk -F : '"'"'{print "PATH is set to"} {for (i=1;i<=NF;i++) {print "["i"]",$i}}'"'"
Funciona quando há aspas simples e duplas na string de alias!alias serve_this_dir='ruby -rrack -e "include Rack;Handler::Thin.run Builder.new{run Directory.new'"'"''"'"'}"'
'\''
é muito mais legível na maioria dos contextos do que'"'"'
. De fato, o primeiro é quase sempre claramente distinto dentro de uma string de aspas simples e, portanto, é apenas uma questão de mapeá-lo semanticamente para o significado de "é uma citação escapada", como acontece com as\"
strings de aspas duplas. Considerando que o último se mistura em uma linha de ticks de cotação e precisa de inspeção cuidadosa em muitos casos para distinguir adequadamente.Eu sempre substituo cada aspas simples incorporada pela sequência:
'\''
(que é: aspas de barra invertida entre aspas) que fecha a sequência, anexa uma aspas simples escapada e reabre a sequência.Costumo criar uma função "quotify" nos meus scripts Perl para fazer isso por mim. Os passos seriam:
Isso praticamente cuida de todos os casos.
A vida fica mais divertida quando você introduz
eval
seus scripts de shell. Você basicamente tem que refazer tudo novamente!Por exemplo, crie um script Perl chamado quotify contendo as instruções acima:
use-o para gerar uma sequência de caracteres corretamente citada:
resultado:
que pode ser copiado / colado no comando alias:
(Se você precisar inserir o comando em uma avaliação, execute o quotify novamente:
resultado:
que pode ser copiado / colado em uma avaliação:
fonte
set -x
eecho "here's a string"
e você verá que executa festançaecho 'here'\''s a string'
. (set +x
Para retornar o comportamento normal)Desde a sintaxe do Bash 2.04
$'string'
(em vez de apenas'string'
; aviso: não confunda com$('string')
) é outro mecanismo de citação que permite seqüências de escape do tipo ANSI C e faz expansão para a versão de citação única.Exemplo simples:
No seu caso:
Sequências de escape comuns funcionam conforme o esperado:
Abaixo está a cópia + documentação relacionada colada de
man bash
(versão 4.4):Palavras da forma $ 'string' são tratadas especialmente. A palavra se expande para cadeia, com caracteres de escape com barra invertida substituídos conforme especificado pelo padrão ANSI C. Seqüências de escape de barra invertida, se presentes, são decodificadas da seguinte maneira:
O resultado expandido é de aspas simples, como se o cifrão não estivesse presente.
Veja Citações e escape: ANSI C como strings no wiki do bash-hackers.org para mais detalhes. Observe também que o arquivo "Bash Changes" ( visão geral aqui ) menciona muito as alterações e correções de bugs relacionadas ao
$'string'
mecanismo de cotação.De acordo com unix.stackexchange.com Como usar um caractere especial como normal? deve funcionar (com algumas variações) no bash, zsh, mksh, ksh93 e FreeBSD e busybox sh.
fonte
echo $'foo\'b!ar'
=>!ar': event not found
> echo $BASH_VERSION
4.2.47(1)-release
> echo $'foo\'b!ar'
foo'b!ar
$'
maneira mais provavelmente mais fácil de tentar você mesmo em sistemas mais antigos.e. Bash no longer inhibits C-style escape processing ($'...') while performing pattern substitution word expansions.
Extraído de tiswww.case.edu/php/chet/bash/CHANGES . Ainda funciona em 4.3.42, mas não em 4.3.48.Não vejo a entrada em seu blog (link pls?), Mas de acordo com o manual de referência do gnu :
então bash não vai entender:
alias x='y \'z '
no entanto, você pode fazer isso se estiver entre aspas duplas:
fonte
Posso confirmar que o uso
'\''
de uma única citação dentro de uma sequência de aspas simples funciona no Bash e pode ser explicado da mesma maneira que o argumento "colar" anteriormente no thread. Suponha que tenhamos uma string entre aspas:'A '\''B'\'' C'
(todas as aspas aqui são aspas simples). Se ele é passado para echo, ele imprime o seguinte:A 'B' C
. Em cada uma,'\''
a primeira citação fecha a cadeia de citação única atual, a seguir\'
cola uma citação única na cadeia de caracteres anterior (\'
é uma maneira de especificar uma citação única sem iniciar uma cadeia de citação) e a última citação abre outra cadeia de citação única.fonte
alias something='A '\''B'\'' C'
resulta emsomething
uma única sequência, portanto, mesmo que o lado direito da tarefa não seja tecnicamente uma única sequência, acho que não importa muito.'A ' + ' + 'B' + ' + ' C'
. Em outras palavras, uma solução para inserir caracteres de aspas simples em uma sequência de aspas simples deve permitir que eu crie essa sequência sozinha e imprima. No entanto, esta solução não funcionará neste caso.STR='\''; echo $STR
. Conforme projetado, o BASH realmente não permite isso.'\''
funciona para o bash. Você poderia apontar quais seções do gnu.org/software/bash/manual/bashref.html especificam esse comportamento?Ambas as versões estão funcionando, com concatenação usando o caractere de aspas simples (\ ') ou com concatenação colocando o caractere de aspas simples entre aspas duplas ("'").
O autor da pergunta não percebeu que havia uma citação única extra (') no final de sua última tentativa de fuga:
Como você pode ver na bela peça anterior da arte ASCII / Unicode, a última aspas simples (\ ') com escape é seguida por uma aspas simples desnecessária ('). Usar um marcador de sintaxe como o presente no Notepad ++ pode ser muito útil.
O mesmo vale para outro exemplo como o seguinte:
Essas duas belas instâncias de aliases mostram de maneira muito complexa e ofuscada como um arquivo pode ser alinhado. Ou seja, de um arquivo com muitas linhas, você obtém apenas uma linha com vírgulas e espaços entre o conteúdo das linhas anteriores. Para entender o comentário anterior, a seguir é um exemplo:
fonte
Exemplo simples de escape de aspas no shell:
Isso é feito finalizando um já aberto (
'
), colocando um escapado (\'
) e depois outro ('
). Essa sintaxe funciona para todos os comandos. É uma abordagem muito semelhante à 1ª resposta.fonte
Não estou abordando especificamente a questão das citações porque, bem, às vezes, é apenas razoável considerar uma abordagem alternativa.
que você pode chamar como:
a ideia é que agora você pode alias isso sem se preocupar com aspas:
ou, se você precisar incluir
#
todas as chamadas por algum motivo:que você pode chamar como:
então, é claro, um alias é:
(opa, acho que meio que resolvi a citação :)
fonte
Como não é possível colocar aspas simples em seqüências de caracteres entre aspas, a opção mais simples e legível é usar uma sequência HEREDOC
No código acima, o HEREDOC é enviado ao
cat
comando e a saída disso é atribuída a uma variável por meio da notação de substituição de comando$(..)
É necessário colocar uma única cotação no HEREDOC, pois ele está dentro de um
$()
fonte
dash
qual é o shell padrão nos scripts iniciantes do Ubuntu e em outros lugares.Eu apenas uso códigos de shell ... por exemplo,
\x27
ou\\x22
conforme aplicável. Sem problemas, realmente.fonte
x27
(no CentOS 6.6)A maioria dessas respostas ocorre no caso específico sobre o qual você está perguntando. Há uma abordagem geral que um amigo e tenho desenvolvido que permite arbitrária citando em caso de necessidade de citação do bash comandos através de várias camadas de expansão shell, por exemplo, através de ssh,
su -c
,bash -c
, etc. Há um núcleo primitivo você precisa, aqui no bash nativo:Isso faz exatamente o que diz: aspas de cada argumento individualmente (após a expansão do bash, é claro):
Faz o óbvio para uma camada de expansão:
(Observe que as aspas duplas
$(quote_args ...)
são necessárias para transformar o resultado em um único argumento parabash -c
.) E pode ser usado de maneira mais geral para citar corretamente através de várias camadas de expansão:O exemplo acima:
quote_args
individualmente e, em seguida, combina a saída resultante em um único argumento com as aspas duplas internas.bash
,-c
e o resultado já uma vez citado a partir do passo 1, e em seguida, combina o resultado em uma única discussão com as aspas duplas exteriores.bash -c
.Essa é a ideia em poucas palavras. Você pode fazer algumas coisas bem complicadas com isso, mas precisa ter cuidado com a ordem da avaliação e com quais substrings são citados. Por exemplo, o seguinte faz as coisas erradas (para alguma definição de "errado"):
No primeiro exemplo, o bash se expande imediatamente
quote_args cd /; pwd 1>&2
para dois comandos separadosquote_args cd /
epwd 1>&2
, portanto, o CWD permanece/tmp
quando opwd
comando é executado. O segundo exemplo ilustra um problema semelhante para globbing. De fato, o mesmo problema básico ocorre com todas as expansões do bash. O problema aqui é que uma substituição de comando não é uma chamada de função: está literalmente avaliando um script bash e usando sua saída como parte de outro script bash.Se você tentar simplesmente escapar dos operadores de shell, falhará porque a cadeia resultante transmitida
bash -c
é apenas uma sequência de cadeias citadas individualmente que não são interpretadas como operadores, o que é fácil de ver se você faz eco à cadeia que seria foram passados para o bash:O problema aqui é que você está citando demais. O que você precisa é que os operadores não sejam cotados como entrada para o anexo
bash -c
, o que significa que eles precisam estar fora da$(quote_args ...)
substituição de comando.Consequentemente, o que você precisa fazer no sentido mais geral é citar shell cada palavra do comando que não pretende ser expandida no momento da substituição do comando separadamente e não aplicar nenhuma citação extra aos operadores do shell:
Depois de fazer isso, a sequência inteira é um jogo justo para citar ainda mais os níveis arbitrários de avaliação:
etc.
Esses exemplos podem parecer exagerados, considerando que palavras como
success
,sbin
epwd
não precisam ser citadas pelo shell, mas o ponto-chave a ser lembrado ao escrever um script com entrada arbitrária é que você deseja citar tudo o que não tem certeza absoluta de que não é ' Não é necessário citar, porque você nunca sabe quando um usuário lançará umRobert'; rm -rf /
.Para entender melhor o que está acontecendo debaixo das cobertas, você pode brincar com duas pequenas funções auxiliares:
que enumerará cada argumento em um comando antes de executá-lo:
fonte
vagrant ssh -c {single-arg} guest
. Ele{single-arg}
precisa ser tratado como um único argumento, porque o vagrant aceita o próximo argumento depois como o nome do convidado. A ordem não pode ser alterada. Mas eu precisava passar um comando e seus argumentos dentro{single-arg}
. Então eu usei o seuquote_args()
citar o comando e seus argumentos, e colocar aspas em torno do resultado, e funcionou como um encanto:vagrant ssh -c "'command' 'arg 1 with blanks' 'arg 2'" guest
. Obrigado!!!IMHO, a resposta real é que você não pode escapar de aspas simples em strings de aspas simples.
É impossível.
Se presumimos que estamos usando o bash.
Do manual do bash ...
Você precisa usar um dos outros mecanismos de escape de cadeia "ou \
Não há nada mágico sobre
alias
nisso que exija o uso de aspas simples.Ambos os trabalhos a seguir no bash.
O último está usando \ para escapar do caractere de espaço.
Também não há nada mágico no # 111111 que exija aspas simples.
As seguintes opções alcançam o mesmo resultado que as outras duas opções, pois o alias rxvt funciona conforme o esperado.
Você também pode escapar do problemático # diretamente
fonte
No exemplo dado, basta usar aspas duplas em vez de aspas simples como mecanismo de escape externo:
Essa abordagem é adequada para muitos casos em que você apenas deseja passar uma string fixa para um comando: verifique como o shell interpretará a string de aspas duplas por meio de um
echo
e, se necessário, escape caracteres com barra invertida.No exemplo, você verá que aspas duplas são suficientes para proteger a string:
fonte
Obviamente, seria mais fácil simplesmente colocar entre aspas duplas, mas qual é o desafio nisso? Aqui está a resposta usando apenas aspas simples. Estou usando uma variável em vez de,
alias
então é mais fácil imprimir para prova, mas é o mesmo que usaralias
.Explicação
A chave é que você pode fechar a aspas simples e reabri-las quantas vezes quiser. Por exemplo,
foo='a''b'
é o mesmo quefoo='ab'
. Assim, você pode fechar a aspas simples, inserir uma aspas simples literal\'
e reabrir a próxima aspas simples.Diagrama de detalhamento
Este diagrama deixa claro usando colchetes para mostrar onde as aspas simples são abertas e fechadas. As aspas não são "aninhadas", como podem ser parênteses. Você também pode prestar atenção ao realce de cores, que é aplicado corretamente. As strings citadas são marrons, enquanto as
\'
são pretas.(Essa é essencialmente a mesma resposta que a de Adrian, mas acho que isso explica melhor. Também a resposta dele tem duas aspas simples supérfluas no final.)
fonte
'\''
método que eu recomendo sobre o'"'"'
método que geralmente é mais difícil para os humanos lerem.Aqui está uma elaboração sobre A resposta verdadeira única, mencionada acima:
Às vezes eu vou baixar usando o rsync over ssh e tenho que escapar de um nome de arquivo com um 'DUAS VEZES! (OMG!) Uma vez para o bash e outra para o ssh. O mesmo princípio de delimitadores de cotação alternados está em ação aqui.
Por exemplo, digamos que queremos obter: as histórias de Louis Theroux em LA ...
E eis! Você acaba com isso:
que é muito trabalho para um pouco '- mas lá vai você
fonte
Explicação da implementação:
aspas duplas, para que possamos gerar facilmente aspas simples e usar a
${...}
sintaxeA pesquisa e substituição do bash se parece com:
${varname//search/replacement}
estamos substituindo
'
por'\''
'\''
codifica um único'
assim:'
termina a citação única\'
codifica a'
(a barra invertida é necessária porque não estamos entre aspas)'
inicia a citação única novamenteo bash concatena automaticamente as strings sem espaço em branco entre
há um
\
antes de cada\
e'
porque essas são as regras de escape${...//.../...}
.PS Sempre codifique para seqüências de caracteres simples entre aspas, porque elas são muito mais simples do que cadeias de caracteres entre aspas duplas.
fonte
Outra maneira de corrigir o problema de muitas camadas de cotação aninhada:
Você está tentando colocar muito em um espaço muito pequeno, então use uma função bash.
O problema é que você está tentando ter muitos níveis de aninhamento, e a tecnologia básica de alias não é poderosa o suficiente para acomodar. Use uma função bash como esta para fazer com que as aspas simples e duplas de retorno e os parâmetros passados sejam todos tratados normalmente como seria de esperar:
Em seguida, você pode usar suas variáveis $ 1 e $ 2 e aspas simples e duplas e back ticks sem se preocupar com a função de alias que destrói sua integridade.
Este programa imprime:
fonte
Se você possui o GNU Parallel instalado, pode usar sua citação interna:
A partir da versão 20190222, você pode até
--shellquote
várias vezes:Ele irá citar a string em todos os shells suportados (não apenas
bash
).fonte
Esta função:
permite citar
'
dentro'
. Use como este:Se a linha a citar se tornar mais complexa, como aspas duplas misturadas com aspas simples, pode ser bastante complicado fazer com que a string cite dentro de uma variável. Quando tais casos aparecerem, escreva a linha exata que você precisa citar dentro de um script (semelhante a este).
Saída:
Todas as cadeias citadas corretamente entre aspas simples.
fonte
Se você estiver gerando a string do shell no Python 2 ou Python 3, o seguinte pode ajudar a citar os argumentos:
Isso produzirá:
fonte
Aqui estão meus dois centavos - no caso, se alguém quiser ser
sh
portável, não apenasbash
específico (a solução não é muito eficiente, porém, ao iniciar um programa externosed
):quote.sh
(ou apenasquote
) em algum lugar do seuPATH
:Um exemplo:
E, claro, isso se converte novamente:
Explicação: basicamente temos que incluir a entrada entre aspas
'
e, em seguida, também substituir qualquer aspas simples nesse micro-monstro:'"'"'
(finalize a cotação de abertura com um emparelhamento'
, escape da aspas simples encontrada envolvendo-as com aspas duplas -"'"
e então finalmente emitir uma nova abertura aspas simples'
ou em pseudo-notação:' + "'" + ' == '"'"'
)Uma maneira padrão de fazer isso seria usar
sed
o seguinte comando de substituição:Um pequeno problema, porém, é que, para usá-lo no shell, é necessário escapar de todos esses caracteres de aspas simples na própria expressão sed - o que leva a algo como
(e uma boa maneira de criar esse resultado é alimentar a expressão original
s/\(['][']*\)/'"\1"'/g
nos scripts de Kyle Rose 'ou George V. Reilly).Finalmente, faz sentido esperar que a entrada venha,
stdin
já que passá-la por argumentos da linha de comando já pode ser um problema demais.(Ah, e pode ser que desejemos adicionar uma pequena mensagem de ajuda para que o script não pare quando alguém o executa como se
./quote.sh --help
perguntando o que ele faz.)fonte
Aqui está outra solução. Essa função usa um único argumento e o cita adequadamente usando o caractere de aspas simples, assim como a resposta votada acima explica:
Então, você pode usá-lo desta maneira:
fonte