如何在POSIX shell中迭代双引号字符串?
我试图检查脚本所依赖的所有非POSIX命令是否在脚本继续执行其主要任务之前都存在。这将帮助我确保我的脚本不会因为缺少命令而在以后生成错误 我希望将所有此类非POSIX命令的列表保存在名为如何在POSIX shell中迭代双引号字符串?,shell,for-loop,posix,Shell,For Loop,Posix,我试图检查脚本所依赖的所有非POSIX命令是否在脚本继续执行其主要任务之前都存在。这将帮助我确保我的脚本不会因为缺少命令而在以后生成错误 我希望将所有此类非POSIX命令的列表保存在名为DEPS的变量中,以便随着脚本的发展和对更多命令的依赖,我可以编辑此变量 我希望脚本支持带有空格的命令,例如my program 这是我的剧本 #!/bin/sh DEPS='ssh scp "my program" sftp' for i in $DEPS do echo "Checking $i .
DEPS
的变量中,以便随着脚本的发展和对更多命令的依赖,我可以编辑此变量
我希望脚本支持带有空格的命令,例如my program
这是我的剧本
#!/bin/sh
DEPS='ssh scp "my program" sftp'
for i in $DEPS
do
echo "Checking $i ..."
if ! command -v "$i"
then
echo "Error: $i not found"
else
echo "Success: $i found"
fi
echo
done
但是,这不起作用,因为“我的程序”
被拆分为两个单词,而for
循环会迭代:“我的
和程序”
,如下面的输出所示
# sh foo.sh
Checking ssh ...
/usr/bin/ssh
Success: ssh found
Checking scp ...
/usr/bin/scp
Success: scp found
Checking "my ...
Error: "my not found
Checking program" ...
Error: program" not found
Checking sftp ...
/usr/bin/sftp
Success: sftp found
我期望的结果是:
# sh foo.sh
Checking ssh ...
/usr/bin/ssh
Success: ssh found
Checking scp ...
/usr/bin/scp
Success: scp found
Checking my program ...
Error: my program not found
Checking sftp ...
/usr/bin/sftp
Success: sftp found
如何在保持脚本POSIX兼容的同时解决此问题?之所以会出现这种情况,是因为参数扩展后的步骤是字符串拆分和全局扩展,而不是语法级别的解析(例如处理引用)。要回到解析过程的开始,需要使用
eval
坦率地说,最好的方法是:
也就是说,您可以选择使用
$@
来存储内容,可以使用eval
进行设置,尽管这很危险:
deps='goodbye "cruel world"'
eval "set -- $deps"
for program; do
echo "processing $program"
done
如果在函数内部执行此操作,将只覆盖函数的参数列表,而不修改全局列表
或者,
eval“yourfunction$deps”
将具有相同的效果,将函数中的参数列表设置为对$deps
的内容运行所有常规解析和扩展阶段的结果这是因为参数扩展后的步骤是字符串拆分和全局扩展,而不是语法级别的解析(例如处理引用)。要回到解析过程的开始,需要使用eval
坦率地说,最好的方法是:
也就是说,您可以选择使用
$@
来存储内容,可以使用eval
进行设置,尽管这很危险:
deps='goodbye "cruel world"'
eval "set -- $deps"
for program; do
echo "processing $program"
done
如果在函数内部执行此操作,将只覆盖函数的参数列表,而不修改全局列表
或者,
eval“yourfunction$deps”
将具有相同的效果,将函数中的参数列表设置为对$deps
的内容运行所有常规解析和扩展阶段的结果,因为脚本在您的控制下,您可以合理安全地使用eval
,所以@Charles Duffy的答案是一个简单而好的解决方案。使用它。:)
也可以考虑使用<代码> AutoCuf生成通常的代码>配置< /COD>脚本,为您所需要的做好工作——例如检查命令和更多…至少,检查一些配置脚本,了解如何解决常见问题
如果您想使用自己的实现:- 将依赖项分为两组
- core_deps-unix工具,脚本本身通常需要的工具,如
,sed
cat
等。这些程序的名称和$PATH中都不包含空格cp
- runtime_deps—程序,应用程序所需的内容,但脚本本身不需要
- core_deps-unix工具,脚本本身通常需要的工具,如
- 分两步进行检查(或更多,例如,如果需要检查,例如库)
- 切勿将
循环用于以空格分隔的元素,除非将它们作为函数参数-因此可以使用for
“$@”
_check_core_deps() {
for _cmd
do
_cpath=$(command -v "$_cmd")
case "$_cpath" in
/*) continue;;
*) echo "Missing install dependency [$_cmd] - can't continue" ; exit 1 ;;
esac
done
return 0
}
core_deps="grep sed hooloovoo cp" #list of "core" commands - they doesn't contains spaces
_check_core_deps $core_deps || exit 1
以上内容将在不存在的“hooloovoo”命令下爆炸:
现在您可以安全地继续,安装脚本所需的所有核心命令都可用。在下一步中,您可以检查其他奇怪的依赖项
一些想法:
# function what returns your dependecies as lines from HEREDOC
# (e.g. could contain any character except "\n")
# you can decorate the dependecies with comments...
# because we have sed (checked in the 1st step, can use it)
# if want, you can add "fields" too, for some extended functinality with an specified delimiter
list_deps() {
_sptab=$(printf " \t") # the $' \t' is approved by POSIX for the next version only
#the "sed" removes comments and empty lines
#the UUOC (useless use of cat) is intentional here
#for example if you want add "tr" before the "sed"
#of course, you can remove it...
cat - <<DEPS |sed "s/[$_sptab]*#.*//;/^[$_sptab]*$/d"
########## DEPENDECIES ############
#some comment
ssh
scp
sftp
#comment
#bla bla
my program #some comment
/Applications/Some Long And Spaced OSX Apllication.app
DEPS
########## END of DEPENDECIES #####
}
_check_deps() {
#in the "while" loop you can use IFS=: or such and adding anouter variable to read
#for getting more fields for some extended functionality
list_deps | while read -r line
do
#do any checks with the line
#implement additional functionalities as functions
#etc...
#remember - your in an subshell here
printf "command:%s\n" "$line"
done
}
_check_deps
- 永远不要使用大写的变量,如“DEPS”。。。它们只适用于环境变量
eval
,因此@Charles Duffy的答案是一个简单而好的解决方案。使用它。:)
也可以考虑使用<代码> AutoCuf生成通常的代码>配置< /COD>脚本,为您所需要的做好工作——例如检查命令和更多…至少,检查一些配置脚本,了解如何解决常见问题
如果您想使用自己的实现:- 将依赖项分为两组
- core_deps-unix工具,脚本本身通常需要的工具,如
,sed
cat
等。这些程序的名称和$PATH中都不包含空格cp
- runtime_deps—程序,应用程序所需的内容,但脚本本身不需要
- core_deps-unix工具,脚本本身通常需要的工具,如
- 分两步进行检查(或更多,例如,如果需要检查,例如库)
- 切勿将
循环用于空格分隔的元素,除非您将它们作为函数参数,这样您就可以使用for
deps="ssh scp my program sftp " while read -r cmd; do printf "Checking $cmd ...\n" if ! command -v "$cmd"; then printf "Error: $i not found\n" else printf "Success: $cmd found\n" fi printf "\n" done <<EOF $deps EOF