我正在尝试根据导入的 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
有一种更有用、更常用(类似于tcl
or 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
中的语法相同,因此您无法轻松地将命令的输出放入关联数组中,除非像其他人所示使用循环一次执行一个元素赋值。ksh93
array=([key1]=value1 [key2]=value2)
请注意,bash
关联数组(与ksh93
或相对zsh
)有一个限制,即键不能是空字符串(这里不是问题)。这次共享的另一个限制ksh93
是键和值都不能包含 NUL 字节(这里也不是问题)。
(ksh93 从一开始(1993 年)就支持关联数组,并zsh
于 1998 年(3.1.5-pws-3)和bash
2009 年(4.0)添加了支持)