가져온 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 항목 목록을 반환한 다음 변수 확장을 사용하여 분할하여 단일 루프(및 좋은 측정을 위한 한 번의 호출)로 배열을 구축할 수 있습니다.
#!/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
:과 동일하므로 다른 사람들이 보여준 것처럼 한 번에 한 요소씩 할당을 수행하기 위해 루프를 사용하지 않고 명령의 출력을 연관 배열에 쉽게 넣을 수 없습니다.ksh93
array=([key1]=value1 [key2]=value2)
bash
연관 배열(및 ksh93
/상대 배열 ) 에는 zsh
키가 빈 문자열이 될 수 없다는 제한이 있습니다(여기에서는 문제가 되지 않음). 이 공유의 또 다른 제한 사항 ksh93
은 키나 값 모두 NUL 바이트를 포함할 수 없다는 것입니다(여기에서도 문제가 되지 않음).
(ksh93은 처음(1993)부터 연관 배열을 지원했으며 zsh
1998(3.1.5-pws-3) 및 bash
2009(4.0)에 지원이 추가되었습니다)