O que '\ time', 't \ ime' e '\ cd' realmente fazem? (diversão com barras invertidas em conchas)

9

Durante a discussão sobre as diferenças entre /usr/bin/time e o shell (bash e zsh) incorporado em time , alguém mencionou que é possível usar \time como abreviação para obter /usr/bin/time .

Primeiro, pareceu um bom atalho inocente, mas algumas perguntas surgiram:

  • Por que o t\ime também funciona?
  • Por que \cd altera o diretório, mesmo que /usr/bin/cd ¹ não o faça?

Então, obviamente, \foo não é equivalente a $(which foo) . A questão é agora:

O comportamento observado de \foo no bash e no zsh é coberto pela definição POSIX de um shell e, se for, por que ele se comporta da mesma forma?

Nota de rodapé 1: /usr/bin/cd é, no meu sistema,

#!/bin/sh
builtin cd "$@"
    
por Jonas Schäfer 15.03.2016 / 14:28

1 resposta

14

t\ime ou \cd (ou "tim"e ou 'cd' ou ${-##*}time ou ${-+time} e todas as outras combinações de cotações e expansões que você poderia imaginar que acabariam resolvendo para time ou cd ), é isso: outra maneira de escrever cd e time .

No entanto, isso acabaria resolvendo para cd ou time em um momento posterior da análise e interpretação da sintaxe do shell. Em particular, isso acontece muito tempo após o reconhecimento da palavra-chave shell e a substituição do alias .

Assim, no momento em que o shell está procurando palavras-chave em seu idioma, ele não está reconhecendo ti\me como a palavra-chave time shell. Então um:

ti\me echo test

seria reconhecido pelo shell como um comando simples, em oposição à palavra-chave time seguida por um comando simples.

Em seguida, a cotação em ti\me seria processada (aqui, a barra invertida está citando o caractere m , que não precisa ser cotado de qualquer maneira, o caractere de citação é removido, você recebe time ) e time < em> comando seria consultado como qualquer outro comando (na lista de arquivos embutidos, funções e executáveis em $PATH . O mais provável é que /bin/time aqui)

Para cd , não há nenhuma palavra-chave cd na linguagem do shell, apenas um comando cd builtin (que tem precedência sobre o /usr/bin/cd ). No entanto, se você definir um alias para cd (como alias cd=pushd ), o mesmo novamente. Como a substituição de alias é feita muito cedo, antes da remoção da cotação, se você tiver um alias para cd e não para \cd (observe que não são muitos os shells que permitem aliases com barras invertidas), escrevendo:

\cd dir

você está certificando-se de que seu cd alias não seja substituído.

Em suma, citando um nome de comando ou qualquer parte dele impede que ele seja visto como uma palavra-chave de shell (palavras-chave sendo coisas como while , for , if , { ... time é uma palavra-chave em alguns apenas shells), e ignora um apelido que você pode ter para isso.

No entanto, ele não força esse comando a ser resolvido para um arquivo executável em $PATH , o comando ainda é pesquisado primeiro entre funções (que pode ser resolvido fazendo command time cmd... ) e < em> builtins (que você pode contornar fazendo env time cmd... , embora eu não saiba de um shell que tenha um comando time embutido).

Observe que as citações também podem influenciar o comportamento dos recursos internos especiais da família typeset / declare / export / local ... em alguns shells. Veja As citações são necessárias para a atribuição local de variáveis? para detalhes.

    
por 15.03.2016 / 14:46