동적으로 생성된 셸 함수를 올바르게 평가할 수 없습니다. (평가란 "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
.