我无法正确评估动态生成的 shell 函数(我所说的评估是指“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"
}
当我用 eval 替换所有 printf '%s' 时,我得到了这个
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
}
及其输出(请注意,这是正确的,它应该看起来与 package_check_repo_printf 的输出相同,因为 set -v 将回显执行的行,因为 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]$
我怎样才能让它正常工作?
注意:需要明确的是,我的目标是使该函数基于 EVAL 而不是基于 PRINTF
一个更好的例子是这样的(虽然我不确定这是否可以通过另一种方式完成,但它仍然会生成一个可用的 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
我并不完全清楚你在问什么,但这里有一个非常简单的例子,它解决了标题中的问题(如何评估 shell 中动态生成的 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
查看您的原始示例,您似乎想在传入的参数字符串只是代码片段而不是完整的 shell 语句的地方用语句替换语句printf
。eval
该特定问题的解决方案是在将其传递给命令之前生成要执行的整个语句eval
。
我还想回应其他建议反对这种方法的用户的评论。如果我是你,我会考虑考虑一种不依赖命令来实现最终目标的方法eval
。