Adicione uma variável env contendo espaços para~/.zshrc
export SKIP="-Dskip1 -Dskip2"
export SKIP_NO_SPACES="-Dskip3"
Tente usá-lo
set -x
mvn $SKIP $SKIP_NO_SPACES
O comando que está sendo executado é na verdade
+-zsh:108> mvn '-Dskip1 -Dskip2' -Dskip3
Somente a variável que contém espaços é citada.
Como evitar que aspas simples sejam adicionadas?
Se não estiver usando aspas/escapamento, haverá um erro ao abrir o shell:
/.zshrc:export:11: não é válido neste contexto: -Dskip2
Responder1
Acho que você está (meio que) abusando de variáveis de ambiente aqui. Esse espaço faz parte da variável e, quando você estiver realizando a expansão de parâmetros com $
, ele simplesmente passará esse espaço para o comando. mvn
recebe um argumento – o conteúdo da sua variável.
Como Kamil Maciorowski observa corretamente em um comentário, isso é específico do Zsh. O que você está propondo funcionaria no Bash se você deixasse as aspas de fora:
bash-5.0$ export test="foo bar"
bash-5.0$ ls $test
ls: bar: No such file or directory
ls: foo: No such file or directory
bash-5.0$ ls "$test"
ls: foo bar: No such file or directory
Uma alternativa para fazer o que você quer seria umapelido global(também um recurso do Zsh, não do Bash), que pode ser substituído em qualquer lugar da linha. Mantém seus espaços:
$ alias -g SKIP="-Dskip1 -Dskip2"
$ alias -g SKIP2="-Dskip3"
$ mvn SKIP SKIP2
Isso simplesmente "acrescentará" a string onde quer que seja adicionada.
Responder2
O problema não tem nada a ver com citar ou escapar, tem tudo a ver com divisão de palavras (ou a falta dela). Na maioria dos shells, se você usar uma variável que contenha espaços em branco sem colocar aspas duplas, o valor será dividido em "palavras" com base nesse espaço em branco. Portanto, se a variável SKIP
estiver definida como -Dskip1 -Dskip2
(observe que não há aspas ou escapes neste valor) e você a usar como mvn $SKIP
, ela se tornará equivalente a mvn "-Dskip1" "-Dskip2"
.
Mas zsh não é a maioria dos shells e (por padrão) não faz divisão de palavras. Se a variável estiver definida como -Dskip1 -Dskip2
, é isso que está sendo passado para o comando,como um único argumento. As aspas que você vê na set -x
saída não estão realmente lá, elas são apenas adicionadas para deixar explícito que a string inteira está sendo passada como um único argumento.
Existem algumas maneiras de dizer ao zsh que você deseja que a divisão de palavras seja feita. Você pode usar o =
modificador na expansão:
mvn ${=SKIP}
Ou você pode ativar a divisão tipo sh para todas as expansões com uma opção de shell:
setopt shwordsplit
mvn $SKIP
...no entanto, isso pode ter efeitos colaterais desagradáveis, como divisão inesperada de coisas que você pensava serem argumentos únicos e expansão de qualquer coisa que pareça um curinga de nome de arquivo em uma lista de nomes de arquivos. A divisão de palavras do shell tende a causar bugs, e é por isso que está desabilitada por padrão no zsh. A maneira realmente adequada de armazenar múltiplas strings em uma variável é usar um array em vez de uma variável simples:
SKIP=(-Dskip1 -Dskip2)
mvn "${SKIP[@]}"
Isso funcionará em zsh, bash e alguns outros shells (mas não aqueles sem suporte a array). No entanto, você não pode exportar matrizes do zsh (bem, você pode executar export SKIP
, mas isso não faz nada). Matrizes são um recurso do shell, enquanto variáveis de ambiente são algo do sistema operacional que suporta apenas strings simples. Você realmente precisa exportar essas opções ou está apenas usando-as dentro do shell?
Responder3
Aspas simples aparecem na linha de diagnóstico impressa por causa de set -x
. Eles não conseguem mvn
. A variável content ( -Dskip1 -Dskip2
) é mvn
considerada um argumento único porque zsh
você não precisa citar variáveis rigidamente (você faz isso em shells compatíveis com POSIX).
O problema parece estar na forma como zsh
expande as variáveis. Acho que você deseja que a divisão de palavras ocorra quando $SKIP
não está entre aspas (como acontece em outras conchas) mas zsh
normalmente não ocorre.
Use ${=SKIP}
paraacionar divisão de palavras após substituição.
Exemplo:
% SKIP='-Dskip1 -Dskip2'
% printf "%s\n" $SKIP
-Dskip1 -Dskip2
% printf "%s\n" ${=SKIP}
-Dskip1
-Dskip2
%