
インポートされた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を使用して内容全体を直接読み取ることができ、読み取りにコロンで区切るように指示できます。
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エントリのリストを返し、変数拡張を使用して分割して単一のループ(および良い測定のための1回の呼び出し)で配列を構築できます。
#!/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
または同様の)方法があります。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
: と同じなので、他の人が示すように、一度に1つの要素を割り当てるためにループを使用せずに、コマンドの出力を連想配列に簡単に配置することはできません。ksh93
array=([key1]=value1 [key2]=value2)
bash
連想配列(およびksh93
/相対配列)には、zsh
キーを空の文字列にすることはできないという制限があります(ここでは問題ではありません)。この共有のもう1つの制限ksh93
は、キーと値の両方にNULバイトを含めることができないことです(ここでも問題ではありません)。
(ksh93は最初(1993)から連想配列をサポートし、zsh
1998(3.1.5-pws-3)とbash
2009(4.0)にサポートが追加されました)