我用了大约一个小时的时间尝试编写一个非常简单的 bash 脚本,但我从未感到自己如此愚蠢。
因此,我有一个字符串列表(如果重要的话,它们是包管理器的包选择器规范),其中可能包含星号。我需要构建一个保留这些星号的命令行,然后调用一个程序。这是我的天真尝试:
xs="foo/bar */*"
xs_cmd=""
for x in $xs; do
xs_cmd="$xs_cmd -0 $x "
done
echo $xs_cmd
我需要的echo
呼叫相当于
echo -0 foo/bar -0 '*/*'
输出-0 foo/bar -0 */*
。
PS 实际上第一行稍微复杂一些: xs="$some foo/bar */* $(get_others)"
。
如果您在包含的目录中运行此脚本a/b
,那么您将得到-0 foo/bar -0 a/b
。
当我将最后一行改为
echo "$xs_cmd" # note the quotes
我明白了-0 foo/bar -0 a/b
,首先这不是我想要的,因为现在我正在echo
调用单身的论点,而且这告诉我扩展发生得更早,很可能在for
循环中。
但我无法改变路线,for
因为
for x in "$xs"; do # note the quotes
只会使循环迭代一次:(-0 foo/bar */*
有一个-0
)所以添加这些引号肯定不是一个选择。
现在,如果我回到原始脚本并将第一行替换为
xs="foo/bar '*/*'" # note additional single quotes
我明白了-0 foo/bar -0 '*/*'
(单引号不应该在那里)。
似乎我尝试了引号和星号反斜杠转义的所有组合,但我真的不知道现在该怎么办。
答案1
我使用了你原来的脚本,但在第一行(仅)使用单引号,并且它按我想你想要的方式工作(-0
在每个文件路径之前):-
xs='foo/bar */*'
xs_cmd=""
for x in $xs; do
xs_cmd="$xs_cmd -0 $x "
done
echo $xs_cmd
如果任何文件路径中嵌入了空格,那么在使用它时可能会遇到问题。如果是这样,请将循环中的命令更改为:-
xs_cmd="$xs_cmd -0 \"$x\" "
答案2
根据您要实现的目标,您需要引用这些内容*/*
:
xs="foo/bar '*/*'" #!
xs_cmd=""
for x in $xs ; do
xs_cmd="$xs_cmd -0 $x "
done
echo $xs_cmd
eval echo $xs_cmd
eval "echo $xs_cmd"
或使用数组,或两者兼而有之:
xs=("foo/bar" "*/*") #!
xs_cmd=""
for x in "${xs[@]}"; do
xs_cmd="$xs_cmd -0 '$x' " #!
done
echo "$xs_cmd"
eval "echo $xs_cmd"