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
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
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
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 )
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
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))