passando cadeia contendo espaços como argumento da linha de comando a partir do script

1

Estou usando um shell bash no mac.

Eu quero escrever um script de shell 'gac' tal que seja executado

> gac one two three

produz exatamente o mesmo efeito da execução

> git add .
> git commit -m "one two three"

Até agora, meu roteiro é este:

function gac() {
    git add .
    concatenated="'$*'"
    git commit -m "$concatenated"
}

Eu encontrei o truque para concatenar os argumentos do shell em uma única string separada por espaço (segunda linha do script) aqui . O script acima quase funciona, exceto que a mensagem de log lê

a382806 'one two three'

quando uso meu script de shell, em vez de

a382806 one two three

como quando eu digito manualmente

> git commit -m "one two three"

na linha de comando.

Alguma idéia?

    
por Labrador 22.10.2017 / 21:36

1 resposta

4

Quando você coloca aspas duplas ao redor de expansão , como o $* , o texto expandido não está sujeito a divisão de palavras . (Essa é uma das razões para usar aspas duplas em torno de $ expansões; a outra é evitar globbing .) Além disso, dentro de aspas duplas, aspas simples não são tratados especialmente, por isso não fazem citações e não são removidos .

Então, como Michael Homer diz: , você pode apenas omitir as espúrias ' ' marks e sua função deve funcionar. Eu sugiro escrever assim:

gac() {
    git add .
    git commit -m "$*"
}

Você pode usar a palavra-chave function para definir funções no Bash, mas a sintaxe mostrada acima funciona tão bem quanto é portátil em shells ao estilo Bourne.

Para abordar o problema conceitual aqui mais diretamente, esta linha em seu código original mostra que você queria expandir um parâmetro cujo valor continha espaços, de forma que você pudesse passá-lo como um único argumento para git :

    concatenated="'$*'"

Quando você escreve um único argumento que contém espaços, você cita os espaços, geralmente com aspas ao redor da string inteira. A presença de ' ' dentro da " " nessa linha indica que você estava tentando incluir as aspas que você normalmente digitaria.

O motivo pelo qual essa abordagem não funciona é que o próprio shell é o que interpreta suas aspas; eles normalmente não significam nada para o comando executado a partir do shell . Suponha que você tenha o comando:

some-command 'foo bar' baz

Esse comando não transmite aspas para o comando some-command . Em vez disso, ele executa some-command com foo bar como argumento 1 e baz como argumento 2. (Há também um argumento 0, que diz ao programa como ele foi executado; o shell passa some-command para isso.)

O uso de citações permite que você informe o shell onde os argumentos começam e terminam. Normalmente, os espaços informam ao shell para realizar a divisão de palavras, mas você deseja suprimir o significado especial dos espaços para o shell, que é o que a citação faz. Quando as aspas são citadas, como o interior ' ' dentro de " " , isso também remove o seu significado especial their . Então eles não fazem citações, mas são literalmente passados ao seu comando, como git mostrou em seu log:

a382806 'one two three'
    
por 22.10.2017 / 21:52