AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / unix / Perguntas / 421729
Accepted
Weijun Zhou
Weijun Zhou
Asked: 2018-02-04 16:49:55 +0800 CST2018-02-04 16:49:55 +0800 CST 2018-02-04 16:49:55 +0800 CST

Como as aspas duplas no bash são combinadas (emparelhadas)?

  • 772

estou usando GNU bash 4.3.48. Considere os dois comandos a seguir que diferem apenas por um único cifrão.

Comando 1:

echo "(echo " * ")"

Comando 2:

echo "$(echo " * ")"

A saída deles são, respectivamente

(echo  test.txt ppcg.sh )

e

 * 

Portanto, obviamente, no primeiro caso, o *é globbed, o que significa que a primeira aspa acompanha a segunda para formar um par, e a terceira e a quarta formam outro par.

No segundo caso, o *não é globbed e há exatamente dois espaços extras na saída, um antes do asterisco e outro depois, o que significa que a segunda aspa acompanha a terceira e a primeira acompanha a quarta.

Existem outros casos além da $()construção em que as aspas não correspondem à próxima, mas estão aninhadas? Esse comportamento está bem documentado e, em caso afirmativo, onde posso encontrar o documento correspondente?

bash quoting
  • 2 2 respostas
  • 4137 Views

2 respostas

  • Voted
  1. Best Answer
    Michael Homer
    2018-02-04T17:49:09+08:002018-02-04T17:49:09+08:00

    Qualquer uma das construções de aninhamento que podem ser interpoladas dentro de strings pode ter outras strings dentro delas: elas são analisadas como um novo script, até o marcador de fechamento e podem até ser aninhadas em vários níveis de profundidade. Todas as barras começam com um $. Todos eles são documentados em uma combinação do manual Bash e especificação de linguagem de comando shell POSIX.

    Existem alguns casos dessas construções:

    • Substituição de comando por$( ... ) , como você encontrou. POSIX especifica este comportamento :

      Com o $(command)formulário, todos os caracteres após o parêntese de abertura até o parêntese de fechamento correspondente constituem o comando. Qualquer script de shell válido pode ser usado para o comando ...

      As aspas fazem parte de scripts de shell válidos, portanto, são permitidas com seu significado normal.

    • Substituição de comando usando `, também.
    • O elemento "palavra" de instâncias avançadas de substituição de parâmetros, como${parameter:-word} . A definição de "palavra" é :

      Uma sequência de caracteres tratados como uma unidade pelo shell

      - que inclui texto citado e até mesmo citações mistas a"b"c'd'e- embora o comportamento real das expansões seja um pouco mais liberal do que isso e, por exemplo, ${x:-hello world}funcione também.

    • Expansão aritmética com $(( ... )), embora seja amplamente inútil lá (mas você também pode aninhar a substituição de comandos ou expansões de variáveis ​​e, em seguida, colocar aspas utilmente dentro delas). O POSIX afirma que :

      A expressão deve ser tratada como se estivesse entre aspas, exceto que aspas dentro da expressão não são tratadas de forma especial. O shell deve expandir todos os tokens na expressão para expansão de parâmetro, substituição de comando e remoção de citação.

      portanto, esse comportamento é explicitamente necessário. Isso significa que echo "abc $((4 "*" 5))"faz aritmética, em vez de globbing.

      $[ ... ]Observe, porém, que a expansão aritmética de estilo antigo não é tratada da mesma maneira: as aspas serão um erro se aparecerem, independentemente de a expansão estar entre aspas ou não. Este formulário não está mais documentado e não deve ser usado de qualquer maneira.

    • Tradução específica de localidade com$"..." , que na verdade usa o "como um elemento principal. $"é tratado como uma única unidade.

    Há mais um caso de aninhamento que você pode não esperar, não envolvendo aspas, que é com expansão de chaves : {a,b{c,d},e}expande para "a bc bd e". ${x:-a{b,c}d}não aninha, no entanto; é tratado como uma substituição de parâmetro dando " a{b,c", seguido de " d}". Isso também está documentado :

    Quando chaves são usadas, a chave final correspondente é o primeiro '}' não escapado por uma barra invertida ou dentro de uma string entre aspas e não dentro de uma expansão aritmética incorporada, substituição de comando ou expansão de parâmetro.


    Como regra geral, todas as construções delimitadas analisam seus corpos independentemente do contexto circundante (e as exceções são tratadas como bugs ). Em essência, ao ver $(o código de substituição de comando, apenas pede ao analisador para consumir o que puder do corpo como se fosse um novo programa e, em seguida, verifica se o marcador de término esperado (um sem escape )ou ))ou }) aparece quando o subanalisador é executado das coisas que pode consumir.

    Se você pensar sobre o funcionamento de um analisador descendente recursivo , isso é apenas uma recursão simples para o caso base. Na verdade, é mais fácil fazer do que o contrário, uma vez que você tenha interpolação de strings. Independentemente da técnica de análise subjacente, os shells que suportam essas construções fornecem o mesmo resultado.

    Você pode aninhar as citações tão profundamente quanto quiser por meio dessas construções e funcionará conforme o esperado. Em nenhum lugar ficará confuso ao ver uma citação no meio; em vez disso, será o início de uma nova string entre aspas no contexto interior.

    • 15
  2. user232326
    2018-02-04T20:22:35+08:002018-02-04T20:22:35+08:00

    Talvez olhar para os dois exemplos com printf(em vez de echo) ajude:

    $ printf '<%s> ' "(echo " * ")"; echo
    <(echo > <test.txt> <ppcg.sh> <file1> <file2> <file3> <)>
    

    Ele imprime (echo (a primeira palavra, incluindo um espaço à direita), alguns arquivos e a palavra final ).
    O parêntese é apenas parte da string entre aspas (echo .
    O asterisco (agora sem aspas, pois as duas aspas duplas estão emparelhadas) é expandido como um glob para uma lista de arquivos correspondentes.
    E então, o parêntese de fechamento.

    No entanto, seu segundo comando funciona da seguinte maneira:

    $ printf '<%s> ' "$(echo " * ")" ; echo
    < * >
    

    O $inicia uma substituição de comando. Isso inicia uma nova citação.
    O asterisco é citado " * "e é isso que o comando (aqui é um comando e não uma string entre aspas) echogera. Finalmente, printfreformata *e imprime como < * >.

    • 3

relate perguntas

  • exportar variáveis ​​​​env programaticamente, via stdout do comando [duplicado]

  • Problema estranho ao passar variáveis ​​do arquivo de texto

  • Enquanto a linha lê mantendo os espaços de escape?

  • ordem de substituição de processos `te` e `bash`

  • Execute um script muito lento até que seja bem-sucedido

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Como exportar uma chave privada GPG e uma chave pública para um arquivo

    • 4 respostas
  • Marko Smith

    ssh Não é possível negociar: "nenhuma cifra correspondente encontrada", está rejeitando o cbc

    • 4 respostas
  • Marko Smith

    Como podemos executar um comando armazenado em uma variável?

    • 5 respostas
  • Marko Smith

    Como configurar o systemd-resolved e o systemd-networkd para usar o servidor DNS local para resolver domínios locais e o servidor DNS remoto para domínios remotos?

    • 3 respostas
  • Marko Smith

    Como descarregar o módulo do kernel 'nvidia-drm'?

    • 13 respostas
  • Marko Smith

    apt-get update error no Kali Linux após a atualização do dist [duplicado]

    • 2 respostas
  • Marko Smith

    Como ver as últimas linhas x do log de serviço systemctl

    • 5 respostas
  • Marko Smith

    Nano - pule para o final do arquivo

    • 8 respostas
  • Marko Smith

    erro grub: você precisa carregar o kernel primeiro

    • 4 respostas
  • Marko Smith

    Como baixar o pacote não instalá-lo com o comando apt-get?

    • 7 respostas
  • Martin Hope
    rocky Como exportar uma chave privada GPG e uma chave pública para um arquivo 2018-11-16 05:36:15 +0800 CST
  • Martin Hope
    Wong Jia Hau ssh-add retorna com: "Erro ao conectar ao agente: nenhum arquivo ou diretório" 2018-08-24 23:28:13 +0800 CST
  • Martin Hope
    Evan Carroll status systemctl mostra: "Estado: degradado" 2018-06-03 18:48:17 +0800 CST
  • Martin Hope
    Tim Como podemos executar um comando armazenado em uma variável? 2018-05-21 04:46:29 +0800 CST
  • Martin Hope
    Ankur S Por que /dev/null é um arquivo? Por que sua função não é implementada como um programa simples? 2018-04-17 07:28:04 +0800 CST
  • Martin Hope
    user3191334 Como ver as últimas linhas x do log de serviço systemctl 2018-02-07 00:14:16 +0800 CST
  • Martin Hope
    Marko Pacak Nano - pule para o final do arquivo 2018-02-01 01:53:03 +0800 CST
  • Martin Hope
    Kidburla Por que verdadeiro e falso são tão grandes? 2018-01-26 12:14:47 +0800 CST
  • Martin Hope
    Christos Baziotis Substitua a string em um arquivo de texto enorme (70 GB), uma linha 2017-12-30 06:58:33 +0800 CST
  • Martin Hope
    Bagas Sanjaya Por que o Linux usa LF como caractere de nova linha? 2017-12-20 05:48:21 +0800 CST

Hot tag

linux bash debian shell-script text-processing ubuntu centos shell awk ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve