这在 bash 中按预期工作:
> t="ls -l"
> $t #== ls -l
> "$t" #== "ls -l"
ls -l: command not found
但在 zsh 中我得到了这个:
> t="ls -l"
> $t #== "ls -l"
ls -l: command not found
如何强制 shell 像 bash 一样再次解析变量值?
答案1
如果您想要一个扩展为多个参数的变量,请使用数组:
var=(ls -l)
$var
但要存储代码,最明显的存储类型是函数:
myfunction() ls -l
或者:
myfunction() ls -l "$@"
让该函数接受额外的参数传递给ls
.
bash
与大多数其他类似 Bourne 的 shell 一样,在扩展时拆分未加引号的变量这一事实在我看来是一个错误。看它导致的问题类型。但如果您想要这种行为,您可以设置该shwordsplit
选项。您还可以添加globsubst
恢复另一个选项漏洞在其他类似 Bourne 的 shell 中发现bash
,其中变量扩展也受到通配符(又名路径名扩展)的影响。或者使用emulate sh
or执行完整的 shebang emulate ksh
(但会失去更多 zsh 功能)。
无需去那里,您还可以zsh
显式分割变量:
var='ls -l'
$=var # split on $IFS like the $var of bash/sh
${(s[ ])var} # split on spaces only regardless of the value of $IFS
var='*.txt'
echo $~var # do pathname expansion like the $var of bash/sh
var='ls -ld -- *.txt'
$=~var # do both word splitting and filename generation
答案2
该项目涵盖在zsh常见问题解答。
长话短说。有几种方法可以修复该行为:
- 放
setopt shwordsplit
:
setopt shwordsplit t="ls -l" $t
- 使用
eval
(由于可能的安全问题,最好避免使用):
t="ls -l" eval $t
答案3
如果变量已经定义为字符串,则可以使用
${=t}
该=
标志告诉 zsh 在扩展变量时使用分词。