从两个命令的输出创建关联数组

从两个命令的输出创建关联数组

我正在尝试根据导入的 passwd 文件创建用户目录,并尝试将数据加载到关联数组中: array[username]=directory 。我可以将字段加载到单独的数组中,但无法获得正确的关联,因为每个字段都与所有目录关联。

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

答案1

你可以直接用 bash 读取整个内容,告诉 read 以冒号分割:

declare -A userarray
while IFS=: read -r username password uid gid gecos home shell; do
  userarray[$username]=$home
done < /usrmkr/in.out

答案2

eval declare -A USERARRAY=(
    $(awk -F: '{ printf "[\"%s\"]=\"%s\"\n", $1, $6}' /usrmkr/in.out)
)

awk脚本以设置 bash 关联数组的多个元素时所需的格式生成输出[key]=val,并用双引号将键和值 ( ["key"]="value") 括起来,以防键或值中存在空格、制表符等。

我使用\n分隔符来方便您使用awk其他工具对输出进行后处理(尽管awk无论如何,您可以使用其他工具完成您可能想做的大多数事情)。

命令替换应该本身就足够了...但是由于 IMO 中的一个错误bash,如果数组定义中的第一个非空白字符( ... )不是 a [,它只会产生错误消息must use subscript when assigning associative array

例如,以下两种设置 USERARRAY 的尝试都将失败:

$ 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

解决方案是在声明散列数组时使用eval,如我的答案顶部的代码示例所示。或者,

eval declare -A USERARRY=( $UA )

答案3

awk我们可以通过返回 user:dir 条目列表,然后使用变量扩展将其拆分,在单个循环(以及一次调用以进行良好测量)中构建数组,而不是合并两个列表:

#!/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

答案4

zsh有一种更有用、更常用(类似于tclor perl)的方法来声明整个关联数组:array=(key1 value1 key2 value2...)

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

加倍\n,例如ksh93删除换行符作为换行符的特殊状态IFS-空白字符。没有它,foo:\nbar:x将被拆分为“foo”,“bar”,“x”而不是“foo”,“”,“bar”,“x”。

使用 时,语法与:bash中的语法相同,因此您无法轻松地将命令的输出放入关联数组中,除非像其他人所示使用循环一次执行一个元素赋值。ksh93array=([key1]=value1 [key2]=value2)

请注意,bash关联数组(与ksh93或相对zsh)有一个限制,即键不能是空字符串(这里不是问题)。这次共享的另一个限制ksh93是键和值都不能包含 NUL 字节(这里也不是问题)。

(ksh93 从一开始(1993 年)就支持关联数组,并zsh于 1998 年(3.1.5-pws-3)和bash2009 年(4.0)添加了支持)

相关内容