Sintaxe de declaração de matriz de shell C, () vs {}

4

No meu script C-shell (tcsh especificamente) eu tenho tentado declarar um array com seis valores: x, nx, y, ny, z, nz. Depois de algumas tentativas e erros, descobri três formas diferentes de declarar o array que quero:

set arrname = ("x" "nx" "y" "ny" "z" "nz")
set arrname = (x,nx,y,ny,z,nz)
set arrname = {x,nx,y,ny,z,nz}

mas a seguinte linha não funciona:

set arrname = {"x" "nx" "y" "ny" "z" "nz"}

A linha acima produz o seguinte erro:

Missing }.

Minha pergunta é o que é diferente entre () e {} que faz com que a quarta declaração que listei não funcione?

    
por Joshua 27.06.2013 / 22:02

2 respostas

5

{} são expansão de shell, a expansão de Brace é um mecanismo pelo qual cadeias arbitrárias podem ser geradas. Os padrões a serem expandidos por brace assumem a forma de um PREÂMBULO opcional, seguido por uma série de sequências separadas por vírgula entre um par de chaves, seguido por um POSTSCRIPT opcional. O preâmbulo é prefixado em cada string contida nas chaves e o postscript é anexado a cada string resultante, expandindo-se da esquerda para a direita. link detalhado

Então, se você colocar vírgula, você não perderá } error:

   set arrname = {"x","nx","y","ny","z","nz"}
    
por 27.06.2013 / 22:39
5

Isto:

set arrname = ("x" "nx" "y" "ny" "z" "nz")

é uma atribuição de matriz comum (BTW, as aspas não são necessárias neste caso).

Isto:

set arrname = (x,nx,y,ny,z,nz)

também faz $arrname uma matriz, mas tem apenas um elemento, com o valor x,nx,y,ny,z,nz (as vírgulas não são especiais neste contexto).

Isto:

set arrname = {x,nx,y,ny,z,nz}

usa um padrão glob; Assim como {foo,bar}.txt se expande para foo.txt bar.txt , então {x,nx,y,ny,z,nz} expande para x nx y ny z nz .

Aparentemente, o tcsh permite que você use {x,nx,y,ny,z,nz} como uma inicialização de array, mas se você mesmo expandi-lo para:

set arrname = x nx y ny z nz

define $arrname para apenas x e silenciosamente ignora os outros argumentos. Este é um dos muitos problemas estranhos na maneira como os argumentos do comando csh e tcsh parse. Eu usei csh e tcsh por décadas (embora eu mudei principalmente para bash), e eu costumo correr para casos como este, onde eu tenho que experimentar para determinar como algo vai funcionar.

Se você quiser definir $arrname como um valor de matriz, use parênteses e não use vírgulas.

E como barmar mencionado em um comentário, você deve ler isto:

link

O csh e o tcsh têm uma sintaxe de array um pouco mais conveniente do que o bash. Em csh e tcsh, você pode se referir ao terceiro elemento de uma matriz como $arrname[3] ; no bash você tem que adicionar chaves: ${arrname[3]} . Além disso, os arrays do bash são baseados em 0, enquanto os arrays do csh / tcsh são baseados em 1. Mas a maior consistência da sintaxe e semântica do bash, IMHO, mais do que compensa isso.

Alguns exemplos de array simples, em csh:

% set arr = ( 10 20 30 )
% echo $arr
10 20 30
% echo $arr[3]
30

e no bash:

$ arr=(10 20 30)
$ echo ${arr[@]}
10 20 30
$ echo ${arr[*]}
10 20 30
$ echo ${arr[2]}
30

(A sintaxe [@] e [*] se comporta de maneira sutilmente diferente; consulte a documentação do bash para obter detalhes.)

    
por 27.06.2013 / 22:47

Tags