我创建了以下两个最小的 shell 脚本......
测试1
#!/usr/bin/env bash
letterList=$1
for letter in $letterList
do
echo $letter
done
还有一秒钟
测试2
#!/usr/bin/env bash
letterList=$1
test1 $letterList
当我执行时,test1 'A B C'
我得到了所需的输出,A
然后B
是C
.
但是当我执行时,test2 'A B C'
我希望test1 'A B C'
会发生,但实际输出仅为A
.
所以看起来嵌套变量列表似乎没有被读取——换句话说,正在执行的是test1 A
.
发生了什么事,我怎样才能达到预期的结果?
PS:如果相关的话,我正在使用 OS X。
您的代码中没有列表变量。你有一个字符串。
调用
test1
使用未引用的扩展$letterList
。这将使 shell 将其值拆分为空格、制表符和换行符上的多个单词(默认情况下),并且每个单词都将进行文件名通配符(如果它们包含文件名通配符)。结果单词test1
作为单独的参数传递给。在
test1
中,您只需将这些参数中的第一个放入letterList
.如果要将字符串按
$letterList
原样传递给test1
fromtest2
,则需要在调用中将其扩展双引号:顺便说一句,您依赖于 shell 执行
$letterList
循环中的值拆分test1
(与导致您的问题的机制相同),但您永远不会保护代码免受意外执行文件名通配(使用 eg 测试您的脚本test2 "A B C *"
以了解我的意思) .如果要传递列表而不是单个字符串,请
test2
使用列表而不是字符串调用:然后,在 中
test2
,将参数传递给test1
:在这里,
"$@"
将扩展为位置参数列表(脚本的参数),每个单独的参数都被引用。这意味着Hello World
在对 的调用中不会将参数 like 拆分为多个参数test1
,并且字符串* *
也不会拆分为两个,并且不会发生文件名通配。在
test1
中,迭代参数:或者
...或者,如果您只想打印参数,只需
我一直用作
/bin/sh
外壳,因为这里没有任何特定于bash
.运行时
./test2 'a b c'
我们得到:所以最后一行变成:
运行时
test1
我们得到:也就是说,给定的 args
test1
没有用引号括起来,因此它们变成了三个 args 而不是一个。要传递
test1
单个参数,只需将变量括在双引号中。也就是说,将最后一行替换为test2
:请注意,我还添加
./
了提供可执行文件的路径,因为.
在$PATH
.目前尚不清楚您的实际目标是什么。您唯一清楚地说的是您要
test2 'A B C'
输出A
,B
并且C
在三个单独的行上。这是一个不同的解决方案,可以为您提供该结果。一般来说,它似乎给出与 kaylum 的 answer相同的输出。
test2
不变。更改
test1
如下:这自然会改变
test1
. 它现在查看它的所有论点,而不仅仅是$1
. 所以将 在六个单独的行上test1 'A B C' 'D E F'
输出A
,B
,C
,D
,E
and (而不是仅仅, and )。F
A
B
C
我们通常不鼓励使用 ,
$*
因为它将包含空格的字符串分成单独的单词。例如,"lazy dog"
会变成两个词(参数)。但这似乎正是您想要的行为。printf
比echo
文件名以-
或包含\
. 这已经在这个网站上详细讨论过;如果您想了解更多信息,只需搜索即可。