Bax*_*Bax 4 zsh macos macos-catalina
添加一个包含空格的环境变量 ~/.zshrc
export SKIP="-Dskip1 -Dskip2"
export SKIP_NO_SPACES="-Dskip3"
Run Code Online (Sandbox Code Playgroud)
尝试使用它
set -x
mvn $SKIP $SKIP_NO_SPACES
Run Code Online (Sandbox Code Playgroud)
正在执行的命令实际上是
+-zsh:108> mvn '-Dskip1 -Dskip2' -Dskip3
只有包含空格的变量才会被引用。
如何避免添加单引号?
如果根本不使用引用/转义,则打开shell时会出现错误:
/.zshrc:export:11: 在此上下文中无效:-Dskip2
问题与引用或转义无关,与分词(或缺少分词)有关。在大多数 shell 中,如果您使用包含空格的变量而不用双引号将其括起来,则该值将根据该空格拆分为“单词”。因此,如果变量SKIP
设置为-Dskip1 -Dskip2
(请注意,此值中没有引号或转义符),并且您像使用它一样使用它mvn $SKIP
,则它等效于mvn "-Dskip1" "-Dskip2"
.
但是 zsh 不是大多数 shell,并且(默认情况下)它不进行分词。如果变量设置为-Dskip1 -Dskip2
,那么这就是作为单个参数传递给命令的内容。您在set -x
输出中看到的引号实际上并不存在,它们只是被添加以明确表示整个字符串作为单个参数传递。
有几种方法可以告诉 zsh 您想要完成分词。您可以=
在扩展中使用修饰符:
mvn ${=SKIP}
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用 shell 选项为所有扩展打开类似 sh 的拆分:
setopt shwordsplit
mvn $SKIP
Run Code Online (Sandbox Code Playgroud)
...然而,这可能会产生令人不快的副作用,例如意外拆分您认为是单个参数的内容,以及将任何看起来像文件名通配符的内容扩展为文件名列表。Shell 分词往往会导致错误,这就是为什么在 zsh 中默认禁用它的原因。在变量中存储多个字符串的真正正确方法是使用数组而不是普通变量:
SKIP=(-Dskip1 -Dskip2)
mvn "${SKIP[@]}"
Run Code Online (Sandbox Code Playgroud)
这将适用于 zsh、bash 和其他一些 shell(但不适用于那些没有数组支持的 shell)。但是,您不能从 zsh 导出数组(好吧,您可以运行export SKIP
,但它不会执行任何操作)。数组是一个 shell 特性,而环境变量是一个只支持纯字符串的操作系统。您真的需要导出这些选项,还是只是在 shell 中使用它们?
由于 而打印的诊断行中出现单引号set -x
。他们没有得到mvn
。变量内容 ( -Dskip1 -Dskip2
) 作为mvn
单个参数,因为zsh
您不需要严格引用变量(在 POSIX 兼容的 shell 中需要这样做)。
问题似乎出在zsh
扩展变量的方式上。$SKIP
我认为您希望在未加引号时发生分词(就像在其他 shell 中发生的情况一样),但在zsh
其中通常不会发生。
用于在替换后触发分${=SKIP}
词。
例子:
% SKIP='-Dskip1 -Dskip2'
% printf "%s\n" $SKIP
-Dskip1 -Dskip2
% printf "%s\n" ${=SKIP}
-Dskip1
-Dskip2
%
Run Code Online (Sandbox Code Playgroud)
我认为你(有点)在这里滥用环境变量。该空间是变量的一部分,当您使用 执行参数扩展时$
,它只会将该空间传递给命令。mvn
得到一个参数——你的变量内容。
正如 Kamil Maciorowski 在评论中正确观察到的那样,这是 Zsh 特有的。如果您省略引号,您所提议的内容将在 Bash 中起作用:
bash-5.0$ export test="foo bar"
bash-5.0$ ls $test
ls: bar: No such file or directory
ls: foo: No such file or directory
bash-5.0$ ls "$test"
ls: foo bar: No such file or directory
Run Code Online (Sandbox Code Playgroud)
做你想做的另一种选择是全局别名(也是 Zsh 的一个特性,而不是 Bash),它可以在一行中的任何地方替换。它保留其空间:
$ alias -g SKIP="-Dskip1 -Dskip2"
$ alias -g SKIP2="-Dskip3"
$ mvn SKIP SKIP2
Run Code Online (Sandbox Code Playgroud)
这将简单地在添加的任何地方“附加”字符串。
归档时间: |
|
查看次数: |
3519 次 |
最近记录: |