Cria um array associativo a partir da saída de dois comandos

1

Estou tentando criar diretórios de usuários com base em um arquivo passwd importado e estou tentando carregar os dados em uma matriz associativa: array [username] = directory. Eu posso carregar os campos em uma matriz separada, mas não posso obter as associações corretas, pois cada campo é associado a todos os diretórios.

USERLIST=$(cat /usrmkr/in.out | awk -F ":" '{print $1}')
DIRLIST=$(cat /usrmkr/in.out | awk -F ":" '{print $6}')
declare -A USERARRAY

func_StoreData()
{
    USERARRAY[$1]="$2"
    return $?
}

for ((u=0;u<${USERLIST[@]};u++)); do
    func_StoreData ${USERLIST[$u]} ${DIRLIST[$u]}
done

for i in ${!USERARRAY[@]}; do
    echo "making directory for $i in ${USERARRAY[$i]}"
    #Do stuff
done
    
por Gnosthi Seauton 25.07.2016 / 20:59

4 respostas

4

Você pode ler a coisa toda diretamente com o bash, dizendo para a leitura ser dividida em dois-pontos:

declare -A userarray
while IFS=: read -r username password uid gid gecos home shell; do
  userarray[$username]=$home
done < /usrmkr/in.out
    
por 25.07.2016 / 21:45
2
eval declare -A USERARRAY=(
    $(awk -F: '{ printf "[\"%s\"]=\"%s\"\n", $1, $6}' /usrmkr/in.out)
)

O script awk produz saída no formato [key]=val exigido ao configurar vários elementos de uma matriz associativa bash, e aspas duplas tanto a chave quanto o valor ( ["key"]="value" ) no caso de haver espaços, tabulações, etc. nas chaves ou nos valores.

Eu usei \n como separador para facilitar, caso você queira pós-processar a saída awk com alguma outra ferramenta (embora awk possa fazer a maioria das coisas que você pode querer fazer com outras ferramentas , de qualquer maneira).

A substituição de comandos deve ser suficiente por si só ... mas devido ao que é, IMO, um erro em bash , se o primeiro caractere que não é espaço em branco dentro da definição% array ( ... ) é um [ , apenas produz a mensagem de erro must use subscript when assigning associative array .

por exemplo. ambas as tentativas a seguir para definir USERARRAY falharão:

$ bash --version | head -1
GNU bash, version 4.3.46(1)-release (x86_64-pc-linux-gnu)

$ declare -A USERARRAY=($(awk -F: '{ printf "[\"%s\"]=\"%s\"\n", $1, $6}' /usrmkr/in.out))
bash: USERARRAY: $(awk -F: '{ printf "[\"%s\"]=\"%s\"\n", $1, $6}' /usrmkr/in.out): must use subscript when assigning associative array

$ UA=$(awk -F: '{ printf "[\"%s\"]=\"%s\"\n", $1, $6}' /usrmkr/in.out)
$ declare -A USERARRAY=( $UA )
bash: USERARRAY: $UA: must use subscript when assigning associative array

A solução é usar eval ao declarar o array com hash, como no exemplo de código no topo da minha resposta. Ou

eval declare -A USERARRY=( $UA )
    
por 27.07.2016 / 03:58
1

Em vez de mesclar duas listas, podemos construir o array em um único loop (e uma única chamada para awk para uma boa medida) retornando uma lista de entradas user: dir e dividindo isso com expansões de variáveis:

#!/bin/bash

declare -A USERARRAY

for u in $(awk -F: '{print $1 ":" $6}' /usrmkr/in.out)
do
  user=${u%:*}
  dir=${u#*:}
  USERARRAY[$user]=$dir
done
    
por 25.07.2016 / 21:10
0

zsh tem uma maneira mais útil, mais comum (semelhante a tcl ou perl ) de declarar matrizes associativas como um todo: array=(key1 value1 key2 value2...)

typeset -A userarray
IFS=$':\n\n'
userarray=($(cut -d : -f 1,6 < /usrmkr/in.out))

A duplicação de \n , como em ksh93 , remove o status especial da nova linha como caractere de espaço em branco IFS . Sem ele, foo:\nbar:x seria dividido em "foo", "bar", "x" em vez de "foo", "", "bar", "x".

Com bash , a sintaxe é a mesma desajeitada que em ksh93 : array=([key1]=value1 [key2]=value2) , portanto você não pode facilmente obter a saída de um comando em uma matriz associativa diferente de usar um loop fazendo uma única atribuição de elemento em um momento como os outros mostraram.

Observe que as matrizes associativas bash (em oposição a ksh93 ou zsh ) têm uma limitação, pois a chave não pode ser a sequência vazia (não é um problema aqui). Outra limitação, desta vez compartilhada com ksh93 é que nem chave nem valores podem conter o byte NUL (também não é um problema aqui).

(o suporte a matrizes associativas estava em ksh93 desde o início (1993), adicionado a zsh em 1998 (3.1.5-pws-3) e bash em 2009 (4.0))

    
por 25.07.2016 / 22:18