두 명령의 출력에서 ​​연관 배열 만들기

두 명령의 출력에서 ​​연관 배열 만들기

가져온 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더 쉽게 후처리할 수 있도록 구분 기호를 사용합니다 ( 어차피 다른 도구를 사용하여 수행하려는 대부분의 작업을 수행할 수 있지만).awkawk

명령 대체~해야 한다그 자체로는 충분하지만 배열 정의 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또는 와 유사) 방법이 있습니다 .perlarray=(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)부터 연관 배열을 지원했으며 zsh1998(3.1.5-pws-3) 및 bash2009(4.0)에 지원이 추가되었습니다)

관련 정보