쉘에서 동적으로 생성된 if elif else 문을 평가하는 방법

쉘에서 동적으로 생성된 if elif else 문을 평가하는 방법

동적으로 생성된 셸 함수를 올바르게 평가할 수 없습니다. (평가란 "eval" 명령을 의미합니다.)

이는 런타임 시 평가되는 필수 명령문입니다(출력이 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

해당 코드는 다음과 같습니다.

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

모든 printf '%s'를 eval로 바꾸면 다음과 같은 결과가 나타납니다.

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

및 그 출력(이것은 정확합니다. printf가 행을 인쇄하지 않기 때문에 set -v가 실행된 행을 에코하므로 package_check_repo_printf의 출력과 동일해야 합니다):

[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]$

어떻게 하면 제대로 작동하게 할 수 있나요?

참고: 명확히 하자면, 내 목표는 이 함수를 PRINTF 기반이 아닌 EVAL 기반으로 만드는 것입니다.

더 좋은 예는 다음과 같습니다(다른 방법으로 수행할 수 있는지는 확실하지 않지만 여전히 사용 가능한 if 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

출력:

[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]$ 

답변1

나는 당신이 무엇을 요구하는지 완전히 확신하지 못하지만 제목의 문제를 해결하는 매우 간단한 예(셸에서 동적으로 생성된 if 문을 평가하는 방법)는 다음과 같습니다.

#!/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}"

다음은 이 스크립트에 대한 호출 예입니다.

./eval_dynamic_if_then true

그러면 다음과 같은 출력이 생성됩니다.

Command successful!

또는:

./dynamic_if_then false

생산하다:

Command NOT successful!

을 사용하려고 하므로 printf명령을 평가하는 대신 명령만 인쇄하는 조정 방법은 다음과 같습니다.

#!/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}"

이제 이 스크립트의 출력을 평가하려면 다음과 같이 하십시오.

eval "$(print_dynamic_if_then true)"

대체 항목이 인용되어 있습니다. 예를 들어 다음은 작동하지 않습니다.

eval $(print_dynamic_if_then true)

이로 인해 다음과 같은 오류 메시지가 나타납니다.

-bash: syntax error: unexpected end of file

원래 예제를 보면 전달된 인수 문자열이 완전한 쉘 명령문이 아닌 코드 조각인 명령문으로 명령문을 대체하려는 것처럼 보입니다 printf. eval이 특정 문제에 대한 해결책은 실행할 명령문을 명령에 전달하기 전에 전체 명령문을 생성하는 것입니다 eval.

또한 이 접근 방식에 반대하는 다른 사용자의 의견에도 답변하고 싶습니다. 내가 당신이라면 명령에 의존하지 않고 최종 목표를 달성할 수 있는 방법을 고려해볼 것입니다 eval.

관련 정보