bash 执行变量(使用包含在 if 语句中创建的变量的命令)
bash execute variable (with command that held variable which is created inside if statement )
您好,我有如下脚本:
mode= loop1 or loop2
command1="screen -dm -S $name feh *.jpg"
if [ "$(screen -S loop1 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop1" ]];then
name="loop1"
eval "$command1"
elif [ "$(screen -S loop2 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop2" ]] ;then
name="loop2"
eval "$command1"
else
echo "error"
fi
基本上它会检查是否有名为 loop1 或 loop2 的屏幕会话,如果没有,它会评估变量 $command1,其中有另一个变量 $name,当 bash 进入循环时,它应该会发生变化。问题是变量 $command1 在 if 语句开始之前被全局初始化并且在那个时候没有变量 $date.
当循环评估 $command1 时,它不会在循环语句之前使用变量 $name 设置行。
我需要传递给变量 command1 变量名的值
你有什么线索吗?
它应该有效:
mode= loop1 or loop2
command1="screen -dm -S name feh *.jpg"
if [ "$(screen -S loop1 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop1" ]];then
eval "${command1/name/loop1}"
elif [ "$(screen -S loop2 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop2" ]] ;then
eval "${command1/name/loop2}"
else
echo "error"
fi
正如评论中已经指出的,这是一个常见问题解答:http://mywiki.wooledge.org/BashFAQ/050
一个明智的解决方法是将命令重构为参数化函数。条件语句也应该清除椒盐卷饼逻辑——打印命令的退出代码并将其与字符串零进行比较是重新实现 built-in if
条件语句的基本功能的笨拙方法!
mode=loop1 # or loop2
run_feh (} {
screen -dm -S "" feh *.jpg
}
no_screen_of_loop () {
! screen -S "" -X select . && [[ "" != "" ]]
}
if no_screen_of_loop "loop1" "$mode"; then
run_feh "loop1"
elif no_screen_of_loop "loop2" "$mode"; then
run_feh "loop2"
else
echo "error" >&2 # note stderr
fi
如果在 $name
中的值是必要的,则需要进行一些额外的重构。
虽然 chepner 完全 更正您将 运行 陷入 Bash FAQ 050 问题,但您不应该尝试这样做。
这里更直接的问题是评估顺序问题。
当 shell 运行 这条线 command1="screen -dm -S $name feh *.jpg"
它在那个点扩展 $name
(你会注意到,它是 之前 你已经为 name 变量赋值了)。
切换这些(组)行的顺序可以解决这个问题,但对 other Bash FAQ 050 问题没有任何作用。
此外,[ "$(screen -S loop1 -X select . ; echo $?)" != 0 ]
是测试命令是否成功的 return 代码的一种低效且不必要的方法。
[
是一个命令(也称为test
)。它 不是 if
语句语法的组成部分。
shell 中 if
语句的语法是 if <command>; then ... fi
其中 <command>
可以是 return 是 return 代码的任何内容适当地。 [
恰好是那个space.
中常用的命令
但是如果你的命令(screen -S loop1 -X select .
在这种情况下)已经returns success/failure适当那么你可以避免[
完全使用你的命令。
if ! screen -S loop1 -X select . && [[ $mode != "loop1" ]];then
name="loop1"
elif ! screen -S loop2 -X select . && [[ $mode != "loop2" ]] ;then
name="loop2"
else
echo "error"
fi
您好,我有如下脚本:
mode= loop1 or loop2
command1="screen -dm -S $name feh *.jpg"
if [ "$(screen -S loop1 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop1" ]];then
name="loop1"
eval "$command1"
elif [ "$(screen -S loop2 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop2" ]] ;then
name="loop2"
eval "$command1"
else
echo "error"
fi
基本上它会检查是否有名为 loop1 或 loop2 的屏幕会话,如果没有,它会评估变量 $command1,其中有另一个变量 $name,当 bash 进入循环时,它应该会发生变化。问题是变量 $command1 在 if 语句开始之前被全局初始化并且在那个时候没有变量 $date.
当循环评估 $command1 时,它不会在循环语句之前使用变量 $name 设置行。
我需要传递给变量 command1 变量名的值
你有什么线索吗?
它应该有效:
mode= loop1 or loop2
command1="screen -dm -S name feh *.jpg"
if [ "$(screen -S loop1 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop1" ]];then
eval "${command1/name/loop1}"
elif [ "$(screen -S loop2 -X select . ; echo $?)" != 0 ] && [[ $mode != "loop2" ]] ;then
eval "${command1/name/loop2}"
else
echo "error"
fi
正如评论中已经指出的,这是一个常见问题解答:http://mywiki.wooledge.org/BashFAQ/050
一个明智的解决方法是将命令重构为参数化函数。条件语句也应该清除椒盐卷饼逻辑——打印命令的退出代码并将其与字符串零进行比较是重新实现 built-in if
条件语句的基本功能的笨拙方法!
mode=loop1 # or loop2
run_feh (} {
screen -dm -S "" feh *.jpg
}
no_screen_of_loop () {
! screen -S "" -X select . && [[ "" != "" ]]
}
if no_screen_of_loop "loop1" "$mode"; then
run_feh "loop1"
elif no_screen_of_loop "loop2" "$mode"; then
run_feh "loop2"
else
echo "error" >&2 # note stderr
fi
如果在 $name
中的值是必要的,则需要进行一些额外的重构。
虽然 chepner 完全 更正您将 运行 陷入 Bash FAQ 050 问题,但您不应该尝试这样做。
这里更直接的问题是评估顺序问题。
当 shell 运行 这条线 command1="screen -dm -S $name feh *.jpg"
它在那个点扩展 $name
(你会注意到,它是 之前 你已经为 name 变量赋值了)。
切换这些(组)行的顺序可以解决这个问题,但对 other Bash FAQ 050 问题没有任何作用。
此外,[ "$(screen -S loop1 -X select . ; echo $?)" != 0 ]
是测试命令是否成功的 return 代码的一种低效且不必要的方法。
[
是一个命令(也称为test
)。它 不是 if
语句语法的组成部分。
shell 中 if
语句的语法是 if <command>; then ... fi
其中 <command>
可以是 return 是 return 代码的任何内容适当地。 [
恰好是那个space.
但是如果你的命令(screen -S loop1 -X select .
在这种情况下)已经returns success/failure适当那么你可以避免[
完全使用你的命令。
if ! screen -S loop1 -X select . && [[ $mode != "loop1" ]];then
name="loop1"
elif ! screen -S loop2 -X select . && [[ $mode != "loop2" ]] ;then
name="loop2"
else
echo "error"
fi