passa argumentos para funcionar como está

0

Passou por este post: Passar argumentos para funcionar exatamente como está

Mas tenha uma configuração um pouco diferente:

Eu tenho 3 funções bash foo, bar, baz. Eles são configurados da seguinte forma:

foo() {
  bar $1
}

bar() {
  var1=$1
  var2=$2
  echo "$var1" test "$var2"
}
export ENV_VAR_1="1"
export ENV_VAR_2="2 3"

foo "${ENV_VAR_1} ${ENV_VAR_2}"

Espero que a saída seja:

1 test 2 3

Mas a saída é:

1 test 2

Eu entendo porque isso aconteceu. bar foi executado da seguinte forma:

bar 1 2 3

A minha pergunta é: como faço para executar

bar 1 "2 3"

Abordagens que tentei:

foo () {bar "$1"} 
# Out: 1 2 3 test. Makes sense since "1 2 3" is interpreted as a single argument.
    
por user2103008 06.09.2016 / 04:43

2 respostas

1

Isso fornece uma única string como argumento para foo :

foo "${ENV_VAR_1} ${ENV_VAR_2}"

Como $1 não está entre aspas, o shell executa a divisão de palavras e, consequentemente, isso fornece três argumentos para bar :

bar $1

A divisão de palavras é feita em qualquer caractere IFS em S1 . A fonte original desses personagens não é considerada.

Exemplo mais simples

Vamos definir x como:

$ x="${ENV_VAR_1} ${ENV_VAR_2}"

Agora, vamos imprimir "$x" :

$ printf "%s\n" "$x"
1 2 3

Como você pode ver, "$x" é interpretado como um argumento. Por contraste, considere:

$ printf "%s\n" $x
1
2
3

Acima, a divisão de palavras é executada em $x , criando três argumentos.

As strings de shell não têm noção de histórico. A string x não tem registro de 2 3 sendo parte de uma sequência antes de x ser atribuído. A string x consiste apenas de 1 , espaço, 2 , espaço e 3 e a divisão de palavras opera nos espaços.

Alternativa: selecionando seu próprio IFS

Isso produz a saída que você deseja:

$ foo() ( IFS=@;  bar $1; )
$ foo "${ENV_VAR_1}@${ENV_VAR_2}"
1 test 2 3

Em foo , definimos IFS para @ . Consequentemente, toda a divisão de palavras subsequente é executada usando @ como o separador de palavras. Portanto, ao chamar foo , colocamos um @ em qualquer local em que desejamos a divisão de palavras.

    
por 06.09.2016 / 04:48
0

Você está passando um único argumento para a função foo , que é a string de 5 caracteres 1 2 3 . Os três dígitos são separados por espaços. foo não tem motivos para tratar esses espaços de maneira diferente.

Ao combinar ${ENV_VAR_1} e ${ENV_VAR_2} dentro de uma única string, você perdeu informações. Recuperar informações perdidas requer mágica e os computadores não podem fazer mágica. Para manter a separação entre 1 2 e 3 , você precisa alterar a maneira como foo é chamado. Passe dois argumentos separados.

foo "${ENV_VAR_1}" "${ENV_VAR_2}"

Depois, tudo o que você precisa fazer é corrigir a citação na chamada para bar . Ou passe os dois parâmetros:

foo () {
  bar "$1" "$2"
}

ou transmitir toda a lista de parâmetros:

foo () {
  bar "$@"
}
    
por 07.09.2016 / 02:53

Tags