在我的 C-shell 脚本(特别是 tcsh)中,我一直试图声明一个具有六个值的数组:x、nx、y、ny、z、nz。经过反复试验,我发现了三种不同的声明我想要的数组的方法:
set arrname = ("x" "nx" "y" "ny" "z" "nz")
set arrname = (x,nx,y,ny,z,nz)
set arrname = {x,nx,y,ny,z,nz}
Run Code Online (Sandbox Code Playgroud)
但以下行不起作用:
set arrname = {"x" "nx" "y" "ny" "z" "nz"}
Run Code Online (Sandbox Code Playgroud)
上面的行产生以下错误:
Missing }.
Run Code Online (Sandbox Code Playgroud)
我的问题是 () 和 {} 之间有什么不同使我列出的第四个声明不起作用?
这个:
set arrname = ("x" "nx" "y" "ny" "z" "nz")
Run Code Online (Sandbox Code Playgroud)
是一个普通的数组赋值(顺便说一句,在这种情况下不需要引号)。
这个:
set arrname = (x,nx,y,ny,z,nz)
Run Code Online (Sandbox Code Playgroud)
也创建$arrname一个数组,但它只有一个元素,带有值x,nx,y,ny,z,nz(逗号在这种情况下并不特殊)。
这个:
set arrname = {x,nx,y,ny,z,nz}
Run Code Online (Sandbox Code Playgroud)
使用 glob 模式;正如{foo,bar}.txt扩张到foo.txt bar.txt,所以{x,nx,y,ny,z,nz}扩展到x nx y ny z nz。
显然 tcsh 允许您{x,nx,y,ny,z,nz}用作数组初始化,但如果您自己将其扩展为:
set arrname = x nx y ny z nz
Run Code Online (Sandbox Code Playgroud)
它设置$arrname为 justx并默默地忽略其他参数。这是 csh 和 tcsh 解析命令参数的方式中的许多奇怪故障之一。我自己已经使用 csh 和 tcsh 几十年了(尽管我最近主要转向了 bash),而且我经常遇到这样的情况,我必须通过实验来确定某些事情将如何工作。
如果要设置$arrname为数组值,请使用括号,不要使用逗号。
正如 barmar 在评论中提到的,您应该阅读以下内容:
http://www.faqs.org/faqs/unix-faq/shell/csh-whynot/
csh 和 tcsh 确实比 bash 有更方便的数组语法。在 csh 和 tcsh 中,您可以将数组的第三个元素称为$arrname[3]; 在 bash 中,您必须添加大括号:${arrname[3]}. 此外,bash 数组是基于 0 的,而 csh/tcsh 数组是基于 1 的。但是 bash 语法和语义的更大一致性,恕我直言,足以弥补这一点。
一些简单的数组示例,在 csh 中:
% set arr = ( 10 20 30 )
% echo $arr
10 20 30
% echo $arr[3]
30
Run Code Online (Sandbox Code Playgroud)
在 bash 中:
$ arr=(10 20 30)
$ echo ${arr[@]}
10 20 30
$ echo ${arr[*]}
10 20 30
$ echo ${arr[2]}
30
Run Code Online (Sandbox Code Playgroud)
([@]和[*]语法的行为略有不同;有关详细信息,请参阅 bash 文档。)
{} 是 shell 扩展,大括号扩展是一种可以生成任意字符串的机制。要进行大括号扩展的模式采用可选的 PREAMBLE 的形式,后跟一对大括号之间的一系列逗号分隔的字符串,最后是可选的 POSTSCRIPT。前导码作为大括号内包含的每个字符串的前缀,然后将附言附加到每个结果字符串,从左到右扩展。详细链接
因此,如果您输入逗号,则不会出现丢失}错误:
set arrname = {"x","nx","y","ny","z","nz"}
Run Code Online (Sandbox Code Playgroud)