Por que essas opções aninhadas em um script de shell POSIX estão sendo divididas em palavras?

Por que essas opções aninhadas em um script de shell POSIX estão sendo divididas em palavras?

Eu tenho um script count_argsque conta argumentos:

#!/bin/sh
echo $#

Se eu ligar com essas opções, ele me diz que recebe dois argumentos:

$ ./count_args --options '1 2'
2

Mas se eu construir os argumentos em um script test_argsassim:

#!/bin/sh
ARGS="--options '1 2'"
./count_args ${ARGS}

... eu recebo o resultado:

$ ./test_args 
3

Por que o '1 2'ser está dividido no roteiro? Como posso evitar isso de maneira compatível com POSIX,do script de chamada? É possível ainda armazenar argumentos em variáveis ​​de alguma forma para que eu possa separá-los em scripts mais complexos (por exemplo, tendo ARGS_1e ARGS_2)?

Observe que o meu /bin/shé dash.

Responder1

No seu primeiro caso, os argumentos passados ​​para count_argsforam interpretados pelo shell, o shell viu duas palavras --optionse 1 2depois as passou para count_args.

No segundo caso, entre aspas duplas, todos os caracteres, exceto $e, \são tratados como literais. É tarde demais para o shell interpretar as aspas simples, o shell viu o conteúdo da $ARGSvariável como uma string longa --options '1 2', todos os caracteres como literais e não têm nenhum significado especial para o shell.

O uso ${ARGS}sem aspas duplas o submeteu à divisão de campos e expansão de nome de arquivo. Com o valor padrão de IFS, você tem três palavras separadas --options:, '1e 2'.

A melhor maneira de arquivar isso é usando "$@":

#!/bin/sh

set -- --options '1 2'

./count_args "$@"

informação relacionada