Por que não alias foo = 'echo' Esta é uma citação: \ '”' work? [duplicado]

23

Para lembrar a mim mesmo quando tento usar shopt em Zsh em vez de setopt , criei o seguinte alias, testando-o primeiro em um prompt de shell:

$ alias shopt='echo "You\'re looking for setopt. This is Z shell, man, not Bash."'

Apesar da correspondência de aspas simples externas e das aspas duplas internas corresponderem, e o apóstrofo sendo escapado, fui solicitado a terminar de fechar as aspas com:

dquote > _

O que está acontecendo?

Parecia que o escape estava sendo ignorado, ou que precisava escapar em dobro por causa de múltiplos níveis de interpretação ... Então, só para testar essa teoria, eu tentei escapar dela duas vezes (e triplo de escapar dela) , e assim por diante) até:

alias shopt='echo "You\\\\\\\\\\\'re looking for setopt. This is Z shell, man, not Bash." '

e nunca viram comportamentos diferentes. Isso não faz sentido para mim. Que tipo de vodu estranho está impedindo que a casca se comporte como eu esperava?

A solução prática é não usar aspas para echo , já que ele realmente não precisa de nenhuma, e usar aspas duplas para alias , e para escapar do apóstrofo, então ele é ignorado quando o texto é echo ed. Então todos os problemas práticos desaparecem.

Você pode me ajudar? Eu preciso de resolução para este problema desconcertante.

    
por iconoclast 15.04.2018 / 23:58

5 respostas

42

Isso é zsh , man, não fish .

Em zsh , como em todos os shell semelhantes a Bourne (e também csh ), aspas simples são citações strongs, não há como escapar (exceto usando as opções rcquotes como sugeridas por @JdeBP , em que zsh emula rc quotes¹). Você não pode ter uma aspa simples dentro de uma string entre aspas simples, você precisa primeiro fechar a única string entre aspas e digitar a aspa simples literal usando outro mecanismo de aspas (como \ ou " ):

alias shopt='echo "You'\''re looking for setopt. This is Z shell, man, not Bash."'

Ou:

alias shopt='echo "You'"'"'re looking for setopt. This is Z shell, man, not Bash."'

Embora você também possa fazer:

alias shopt="echo \"You're looking for setopt. This is Z shell, man, not Bash.\""

( "..." são mais fracas citações dentro das quais vários caracteres, incluindo \ (aqui usados para escapar do " incorporado) ainda são especiais).

Ou:

alias shopt=$'echo "You\'re looking for setopt. This is Z shell, man, not Bash."'

( $'...' é outro tipo de aspas do ksh93, onde o ' pode ser escapado com \' ).

¹ Em rc , o shell do Plan9, com uma versão para unix-likes também disponível, aspas simples são o único mecanismo de cotação (barras invertidas e aspas duplas são comuns caracteres lá), a única maneira de inserir um aspas simples literal com '' dentro de aspas simples, portanto, com zsh -o rcquotes , você poderia fazer:

alias shopt='echo "You''re looking for setopt. This is Z shell, man, not Bash."'
    
por 16.04.2018 / 00:06
13

As outras respostas explicam bem por que você está vendo esse comportamento. Mas se eu puder fazer uma sugestão de como realmente resolver esse problema:

Não use aliases para nada nem remotamente complicado.

Claro, você pode ligar o seu cérebro em nós tentando descobrir como aninhar N camadas de citações, mas raramente vale a pena para um alias. Quando um alias é complicado o suficiente para que sua cotação se torne não trivial, basta mudar para uma função de shell:

shopt(){
    echo "You're looking for setopt. This is Z shell, man, not Bash."
}

Isso remove uma camada inteira de aspas, permite que você adicione mais código à função de shell mais tarde e, em geral, é muito mais fácil de ler. Ele também permite um controle muito mais preciso sobre como e onde os argumentos são inseridos, em vez da abordagem alias de "apenas substituir o início da linha e deixar as palavras restantes caírem onde puderem". Por exemplo, com o seu alias (corrigido), se você digitar isto:

shopt -s some_opt

... então você terá esta saída:

You're looking for setopt. This is Z shell, man, not Bash. -s some_opt

Isso provavelmente não é o que você queria. A função de shell consumirá qualquer argumento que você passar para ele e silenciosamente os descartará.

    
por 16.04.2018 / 18:20
12
shopt='echo "You\'

Isso não é vodu. Este é o shell POSIX normal que cita em ação. Não há mecanismo de escape dentro de strings entre aspas simples . Eles sempre terminam na próxima citação simples. Existe uma extensão de shell Z que faz com que duas sequências de aspas simples sucessivas obtenham uma aspa simples colocada entre elas, o que você poderia empregar. Ou você pode apenas terminar a cadeia com aspas simples, usar uma aspas simples com escape (ou, na verdade, sem aspas simples) e, em seguida, iniciar uma segunda cadeia entre aspas simples.

Ou você não pode usar contrações nas suas mensagens. ☺

Leitura adicional

  • "Aspas simples" . Linguagem de comando do shell . Especificações Base. IEEE 1003.1: 2017. O grupo aberto
  • "Citando" . Gramática da concha . O manual do Z Shell.
por 16.04.2018 / 00:15
4

Um comentário excluído agora me deu uma dica e me levou até a metade da resposta.

É impossível escapar de uma única citação dentro de uma string entre aspas simples .

Esta limitação não está presente em cadeias duplas entre aspas, já que estou certamente escapando de uma aspa simples dentro de uma string de aspas duplas na minha solução final:

alias shopt="echo You\'re looking for setopt. This is Z shell, man, not Bash."
    
por 16.04.2018 / 00:04
4

Para os dias em que você não sentir vontade de lutar com as aspas, use outro caractere como Unicode U + 2019 em vez de ' para apóstrofos.

Pressione e mantenha pressionado Ctrl + Deslocar e digite u2019 e este caractere aparecerá (er ... dependendo da sua localidade?).

% alias shopt='echo You’re looking for setopt. This is a Z shell, woman, not Bash.'
% shopt -s dotglob
You’re looking for setopt. This is a Z shell, woman, not Bash. -s dotglob

Esse uso de (U + 2019) está correto porque esse caractere é oficialmente destinado a ser usado como um apóstrofo. O Padrão Unicode, Versão 10.0 recomenda explicitamente tal uso. O padrão reconhece que ' (U + 0027) é comumente usado como um apóstrofo devido à sua presença em ASCII e em teclados e parece permitir isso. Mas, em seguida, afirma que (U + 2019) é preferido para apóstrofos usados como pontuação (e fornece uma contração como exemplo). Os únicos apóstrofos para os quais (U + 2019) não são preferidos são aqueles usados como marcas diacríticas em vez de sinais de pontuação; esses são melhores escritos ʼ (U + 02BC). De Apóstrofes (p. 276) na seção 6.2 do padrão :

Apostrophes

U+0027 APOSTROPHE is the most commonly used character for apostrophe. For historical reasons, U+0027 is a particularly overloaded character. In ASCII, it is used to represent a punctuation mark (such as right single quotation mark, left single quotation mark, apostrophe punctuation, vertical line, or prime) or a modifier letter (such as apostrophe modifier or acute accent). Punctuation marks generally break words; modifier letters generally are considered part of a word.

When text is set, U+2019 RIGHT SINGLE QUOTATION MARK is preferred as apostrophe, but only U+0027 is present on most keyboards. Software commonly offers a facility for automatically converting the U+0027 APOSTROPHE to a contextually selected curly quotation glyph. In these systems, a U+0027 in the data stream is always represented as a straight vertical line and can never represent a curly apostrophe or a right quotation mark.

Letter Apostrophe. U+02BC MODIFIER LETTER APOSTROPHE is preferred where the apostrophe is to represent a modifier letter (for example, in transliterations to indicate a glottal stop). In the latter case, it is also referred to as a letter apostrophe.

Punctuation Apostrophe. U+2019 RIGHT SINGLE QUOTATION MARK is preferred where the character is to represent a punctuation mark, as for contractions: “We’ve been here before.” In this latter case, U+2019 is also referred to as a punctuation apostrophe.

An implementation cannot assume that users’ text always adheres to the distinction between these characters. The text may come from different sources, including mapping from other character sets that do not make this distinction between the letter apostrophe and the punctuation apostrophe/right single quotation mark. In that case, all of them will generally be represented by U+2019.

The semantics of U+2019 are therefore context dependent. For example, if surrounded by letters or digits on both sides, it behaves as an in-text punctuation character and does not separate words or lines.

    
por 16.04.2018 / 09:50

Tags