我有一个 bash 脚本,看起来像
#!bin/bash
# array to store my commands
COMMANDS=(route
ls -l
)
# here I want to iterate through the array, run all the commands and take
# screenshot of each after their execution to be put into my lab assignment file.
for (( i=0; i<${#COMMANDS[@]}; i=i+1 )); do
clear
"${COMMANDS[$i]}"
gnome-screenshot -w -f "$i".png
done
但输出看起来像
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default _gateway 0.0.0.0 UG 600 0 0 wlx00e02d4a265d
link-local 0.0.0.0 255.255.0.0 U 1000 0 0 docker0
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 docker0
192.168.43.0 0.0.0.0 255.255.255.0 U 600 0 0 wlx00e02d4a265d
5.png Downloads my_rust_projects sys-info
6.png FINAL450.pdf Pictures Templates
-l: command not found
如何获得ls -l
每个文件的详细条目所需的结果?
答案1
看http://mywiki.wooledge.org/BashFAQ/050,“我试图将命令放入变量中,但复杂的情况总是失败!”
这比您想象的要复杂。每个命令都应该放入一个单独的数组中。由于 bash 没有实现多维数组,因此您需要对其进行一些管理。
尝试这个:
CMD_date=( date "+%a %b %d %Y %T" )
CMD_ls=( ls -l )
CMD_sh=( env MyVar="this is a variable" sh -c 'echo "$MyVar"' )
commands=( date ls sh )
for cmd in "${commands[@]}"; do
declare -n c="CMD_$cmd" # set a nameref to the array
"${c[@]}" # and execute it
done
namerefs 是在 bash 4.3 中引入的——如果你的 bash 较旧,它仍然可以使用间接变量工作
for cmd in "${commands[@]}"; do
printf -v tmp 'CMD_%s[@]' "$cmd"
"${!tmp}" # and execute it
done
更好:使用函数:
CMD_date() {
date "+%a %b %d %Y %T"
}
CMD_ls() {
ls -l
}
CMD_sh() {
env MyVar="this is a variable" sh -c 'echo "$MyVar"'
}
commands=( date ls sh )
for cmd in "${commands[@]}"; do
"CMD_$cmd"
done
答案2
我找到了一个解决方案,但不知道这是一个好主意还是坏主意。任何建议都将受到高度赞赏:
for (( i=0; i<${#COMMANDS[@]}; i=i+1 )); do
clear
# added bash -c in front.
bash -c "${COMMANDS[$i]}"
gnome-screenshot -w -f "$i".png
done