como avaliar uma instrução gerada dinamicamente se elif else na shell

1

estou tendo problemas para obter uma função de shell gerada dinamicamente para avaliar corretamente (avalie o comando i mean "eval")

esta é a declaração desejada a ser avaliada quando executada (exceto que a saída será executada / avaliada por eval)

$ package_check_repo_printf
if [ $(printf '%s\n' "found ${treelistnew0[@]}" | grep -i -e ^"$1") ]
    then
    url=$POOL0$1
    ftp=$ftpPOOL0$1
    echo $1 found in $POOL0
elif [ $(printf '%s\n' "found ${treelistnew1[@]}" | grep -i -e ^"$1") ]
    then
    url=$POOL1$1
    ftp=$ftpPOOL1$1
    echo $1 found in $POOL1
else
    echo $1 not found
fi

e seu código:

package_check_repo_printf() {
for i in ${!REPOS[@]}
    do
if [[ $ifgen == "" ]]
then
printf '%s' "if [ \$(printf '%s\n' \"found \${treelistnew0[@]}\" | grep -i -e ^\"\\") ]
    then
    url=\$POOL0\
    ftp=\$ftpPOOL0\
    echo \ found in \$POOL0
"
ifgen=gen
else
printf '%s' "elif [ \$(printf '%s\n' \"found \${treelistnew$i[@]}\" | grep -i -e ^\"\\") ]
    then
    url=\$POOL$i\
    ftp=\$ftpPOOL$i\
    echo \ found in \$POOL$i
"
fi
done
printf '%s' "else
    echo \ not found
fi"
}

quando eu substituir todos os printf '% s' com eval eu recebo isso

package_check_repo_eval() {
set -v
for i in ${!REPOS[@]}
    do
if [[ $ifgen == "" ]]
then
eval "if [ \$(printf '%s\n' \"found \${treelistnew0[@]}\" | grep -i -e ^\"\\") ]
    then
    url=\$POOL0\
    ftp=\$ftpPOOL0\
    echo \ found in \$POOL0
"
ifgen=gen
else
eval "elif [ \$(printf '%s\n' \"found \${treelistnew$i[@]}\" | grep -i -e ^\"\\") ]
    then
    url=\$POOL$i\
    ftp=\$ftpPOOL$i\
    echo \ found in \$POOL$i
"
fi
done
eval "else
    echo \ not found
fi"
set +v
}

e sua saída (note que para isto ser CORRETO deve parecer o mesmo que a saída do package_check_repo_printf como set -v irá ecoar as linhas executadas como printf não está imprimindo as linhas):

[chakra@chakra-pc UPM]$ unset ifgen
[chakra@chakra-pc UPM]$ package_check_repo_eval
if [ $(printf '%s\n' "found ${treelistnew0[@]}" | grep -i -e ^"$1") ]
    then
    url=$POOL0$1
    ftp=$ftpPOOL0$1
    echo $1 found in $POOL0
bash: syntax error: unexpected end of file
elif [ $(printf '%s\n' "found ${treelistnew1[@]}" | grep -i -e ^"$1") ]
bash: syntax error near unexpected token 'elif'
else
bash: syntax error near unexpected token 'else'
[chakra@chakra-pc UPM]$

como faço para que isso funcione corretamente?

nota: só para ficar claro, meu objetivo é tornar essa função baseada em EVAL em vez de baseada em PRINTF

um exemplo melhor seria este (embora eu não tenha certeza se isso é um outro caminho perecível, mas ainda assim, ele gera uma afirmação utilizável se elif else)

dogs=(1 2 3)
dog=(pink blue white)
colour=(pink black white)
dogs_printf() {
unset ifgen
for i in ${!dogs[@]}
    do
if [[ $ifgen == "" ]]
then
printf '%s' "for i in \${!dogs[@]}
do
if [[ \${dog[i]} == \"\${colour[$i]}\" ]]
    then
    echo dog$i is \"\${colour[$i]}\"
"
ifgen=gen
else
printf '%s' "elif [[ \${dog[i]} == \"\${colour[$i]}\" ]]
    then
    echo dog$i is \"\${colour[$i]}\"
"
fi
done
printf '%s' "else
    echo dog \$i not found
fi
done
"
}
dogs_printf

sua saída:

[chakra@chakra-pc UPM]$ dogs=(1 2 3)
[chakra@chakra-pc UPM]$ dog=(pink blue white)
[chakra@chakra-pc UPM]$ colour=(pink black white)
[chakra@chakra-pc UPM]$ dogs_printf() {
> unset ifgen
> for i in ${!dogs[@]}
>     do
> if [[ $ifgen == "" ]]
> then
> printf '%s' "for i in \${!dogs[@]}
> do
> if [[ \${dog[i]} == \"\${colour[$i]}\" ]]
>     then
>     echo dog$i is \"\${colour[$i]}\"
> "
> ifgen=gen
> else
> printf '%s' "elif [[ \${dog[i]} == \"\${colour[$i]}\" ]]
>     then
>     echo dog$i is \"\${colour[$i]}\"
> "
> fi
> done
> printf '%s' "else
>     echo dog \$i not found
> fi
> done
> "
> }
[chakra@chakra-pc UPM]$ dogs_printf
for i in ${!dogs[@]}
do
if [[ ${dog[i]} == "${colour[0]}" ]]
    then
    echo dog0 is "${colour[0]}"
elif [[ ${dog[i]} == "${colour[1]}" ]]
    then
    echo dog1 is "${colour[1]}"
elif [[ ${dog[i]} == "${colour[2]}" ]]
    then
    echo dog2 is "${colour[2]}"
else
    echo dog $i not found
fi
done
[chakra@chakra-pc UPM]$ for i in ${!dogs[@]}
> do
> if [[ ${dog[i]} == "${colour[0]}" ]]
>     then
>     echo dog0 is "${colour[0]}"
> elif [[ ${dog[i]} == "${colour[1]}" ]]
>     then
>     echo dog1 is "${colour[1]}"
> elif [[ ${dog[i]} == "${colour[2]}" ]]
>     then
>     echo dog2 is "${colour[2]}"
> else
>     echo dog $i not found
> fi
> done
dog0 is pink
dog 1 not found
dog2 is white
[chakra@chakra-pc UPM]$ 
    
por Clark Kent 17.10.2017 / 16:58

1 resposta

0

Não está totalmente claro para mim o que você está perguntando, mas aqui está um exemplo muito simples que aborda a questão no título (como avaliar uma instrução if gerada dinamicamente no shell):

#!/bin/bash

# eval_dynamic_if_then

# Get a command to test from the user
COMMAND="$*"

# Construct an if-then statement using the user
# supplied command and save it to a variable
read -r -d '' IF_THEN <<HEREDOC
if eval "${COMMAND}"; then
  echo "Command successful!"
else
  echo "Command NOT successful!"
fi
HEREDOC

# Evaluate the command
eval "${IF_THEN}"

Aqui está um exemplo de invocação deste script:

./eval_dynamic_if_then true

Isso resulta na seguinte saída:

Command successful!

Alternativamente:

./dynamic_if_then false

produz:

Command NOT successful!

Como você também está experimentando com printf , aqui está uma adaptação que só imprime o comando em vez de avaliá-lo:

#!/bin/bash

# print_dynamic_if_then

# Get a command to test from the user
COMMAND="$*"

# Construct an if-then statement using the user
# supplied command and save it to a variable
read -r -d '' IF_THEN <<HEREDOC
if eval "${COMMAND}"; then
  echo "Command successful!"
else
  echo "Command NOT successful!"
fi
HEREDOC

# Print the command
printf "${IF_THEN}"

Agora, para avaliar a saída desse script, você faria algo como o seguinte:

eval "$(print_dynamic_if_then true)"

Observe que a substituição é citada, por ex. o seguinte não funciona:

eval $(print_dynamic_if_then true)

Isso resulta na seguinte mensagem de erro:

-bash: syntax error: unexpected end of file

Examinando seu exemplo original, parece que você queria substituir printf declarações por eval em locais nos quais a sequência de argumentos passada era apenas um fragmento de código e não uma instrução shell completa. A solução para esse problema específico é gerar toda a instrução a ser executada antes de transmiti-la ao comando eval .

Também gostaria de fazer eco aos comentários de outros usuários que recomendaram essa abordagem. Se eu fosse você, eu consideraria pensar em uma maneira de alcançar seu objetivo final sem depender do comando eval .

    
por 17.10.2017 / 18:01