zsh: map comando para array

3

suponha que você tenha uma matriz a=(foo 'bar baz')

existe uma maneira mais óbvia de aplicar um comando / função a cada elemento da matriz e salvar as seqüências resultantes em outra matriz que não esta:

b=()
for e in $a; do
    b+=("$(my_cmd "$e")")
done
    
por flying sheep 17.08.2015 / 13:47

4 respostas

2

Você sempre pode declarar uma função para isso:

map() {
  local arrayname="$1" cmd="$2" i
  shift 2
  eval "$arrayname=()"
  for i do
    eval "$arrayname+=(\"\$($cmd)\")"
  done
}

E use como:

$ a=(a '' bcd)
$ map b 'wc -c <<< "$i"' "$a[@]"
$ echo $b
2 1 4
    
por 17.08.2015 / 14:04
0

Você pode fazer:

eval "b=(" '"$(cmd "$a['{1..$#a}']")"' ")"

Mas isso não é muito legível.

    
por 17.08.2015 / 14:09
0

Se você souber antecipadamente o que o comando está fazendo com os elementos da matriz, poderá usar sinalizadores de expansão de parâmetro (consulte man zshexpn ) para instruir zsh como adaptar a saída do comando à matriz. / p>

Exemplo

Digamos que uma matriz a contenha os nomes dos arquivos e cada arquivo contenha apenas uma linha de texto:

$ a=(foo 'bar baz')
$ cat foo
A
$ cat 'bar baz'
B C

Agora vamos supor, por causa do argumento, que o comando é apenas cat para colocar em uma matriz b do conteúdo dos arquivos. Neste caso, em vez de loop, podemos simplesmente escrever

b=(${(f)"$(cat "${a[@]}")"})

onde (f) divide o resultado de cat em separar palavras em novas linhas.

O resultado é o esperado:

$ echo "${b[1]}"
A
$ echo "${b[2]}"
B C

De acordo com o cenário real, você pode dividir em caracteres diferentes com o sinalizador ps:<character>: . Alguns deles como nova linha (ps:\n:) do exemplo acima ou caractere NULL (ps:(f):) têm abreviação: (0) e %code% respectivamente.

    
por 17.08.2015 / 15:51
0

Apenas uma nota:

você pode diminuir com:

for e ($a) b+=("$(my_cmd "$e")")

Observe que $a faz um loop sobre os elementos não vazios. Para repetir todos os elementos, é "$a[@]" .

    
por 17.08.2015 / 17:34