我尝试了以下代码。
command1="echo"
"${command1}" 'case1'
command2="echo -e"
"${command2}" 'case2'
echo -e 'case3'
输出如下,
case1
echo -e: command not found
case3
case2导致错误但类似情况,case1和case3运行良好。看来带有选项的命令无法被识别为有效命令。
我想知道为什么它不起作用。请教我。非常感谢你。
答案 0 :(得分:5)
command1="echo" "${command1}" 'case1'
作为一种成语,这是一种不好的做法,但没有任何不正确的做法。
command2="echo -e" "${command2}" 'case2'
这是一个名为/usr/bin/echo -e
,的程序,其中空格是其名称的一部分。
# works in this very specific case, but bad practice
command2="echo -e"
$command2 'case2' # WITHOUT THE QUOTES
...这个有效,但只是因为你的命令不够有趣(没有引号,没有反斜杠,没有其他shell语法)。请参阅BashFAQ #50,了解一般情况下这不是一种可接受的做法的原因。
eval
- 不良做法,Oft建议)您经常会看到这一点:
eval "$command1 'case1'"
...在这个非常特殊的情况下,command1
和所有参数都是硬编码的,这并不是特别有害。但是,只有很小的改变,它极其有害:
# SECURITY BUGS HERE
eval "$command1 ${thing_to_echo}"
...如果thing_to_echo='$(rm -rf $HOME)'
,你将度过非常糟糕的一天。
通常,命令不应存储在字符串中。使用功能:
e() { echo -e "$@"; }
e "this works"
...或者,如果你需要逐步建立你的参数列表,一个数组:
e=( echo -e )
"${e[@]}" "this works"
echo -e
echo
的任何实现-e
除了在输出is failing to comply with the relevant POSIX standard上发出字符-e
之外的其他任何内容,建议使用printf
代替({1}}使用部分)。
改为考虑:
# a POSIX-compliant alternative to bash's default echo -e
e() { printf '%b\n' "$*"; }
...这不仅可以提供与非bash shell的兼容性,而且如果使用--enable-xpg-echo-default
或--enable-usg-echo-default
进行编译,或者shopt -s xpg_echo
是BASHOPTS=xpg_echo
,则修复了对POSIX模式下bash的支持设置,或者在启动时shell的环境中是否存在{{1}}。
答案 1 :(得分:2)
如果变量command
包含值echo -e
给shell的命令行是:
"$command" 'case2'
shell将搜索名为echo -e
的命令,其中包含空格
该命令不存在,shell报告错误。
the image linked below, from O'Reilly's Learning the Bash Shell, 3rd Edition中描述了发生这种情况的原因:
Learning the bash Shell, 3rd Edition
By Cameron Newham
...............................................
Publisher: O'Reilly
Pub Date: March 2005
ISBN: 0-596-00965-8
Pages: 352
如果引用变量(按照右箭头),它几乎(直接通过步骤6,7和8)直接执行到步骤12中执行。
因此,搜索的命令没有在空格上分割。
原始图片(由于@CharlesDuffy投诉删除,我不同意,但是好的,让我们转向不可能出错的一方)就在这里:
Link to original image in the web site where I found it.
如果给shell的命令行没有引用:
$command 'case2'
字符串command
在步骤6(参数展开)中展开,然后变量$command
:echo -e
的值在步骤9中划分:“单词拆分”。
然后shell搜索带有参数echo
的命令-e
。
命令echo
“看到”-e
的参数并将echo作为一个选项进行处理。
尝试将命令存储在字符串中是一个非常糟糕的主意 试试这个,仔细想想你会期待什么,然后对执行感到惊讶:
$ command='echo -e case2; echo "next line"'; $command
要查看会发生什么,请执行以下命令:
$ set -vx; $command; set +vx
答案 2 :(得分:-2)
如果我以这种方式发出命令,它可以在我的机器上运行:
cmd2="echo -e"
如果您仍然遇到问题,我建议将选项存储在另一个变量中,这样如果您正在进行shell脚本编写,那么使用类似选项值的多个命令可以利用该变量,所以也尝试这样的事情。
cmd1="echo"
opt1="-e"
$cmd1 $opt1 Hello