가져온 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
댓글
- 기존 답변으로 문제가 해결되면 다음을 통해 수락하는 것이 좋습니다. 체크 표시. 감사합니다!
답변
읽기를 콜론으로 나누라고 말하면서 bash로 전체 내용을 직접 읽을 수 있습니다. :
declare -A userarray while IFS=: read -r username password uid gid gecos home shell; do userarray[$username]=$home done < /usrmkr/in.out
답변
eval declare -A USERARRAY=( $(awk -F: "{ printf "[\"%s\"]=\"%s\"\n", $1, $6}" /usrmkr/in.out) )
awk
스크립트는 [key]=val
형식으로 출력을 생성합니다. bash 연관 배열의 여러 요소를 설정할 때 필요하며 키 또는 값에 공백, 탭 등이있는 경우 키와 값 (["key"]="value"
)을 모두 큰 따옴표로 묶습니다. .
\n
를 구분자로 사용하여 awk
다른 도구를 사용하여 출력합니다 (awk
는 어쨌든 다른 도구로 수행 할 수있는 대부분의 작업을 수행 할 수 있음).
명령 대체 만으로 충분합니다 .. . 그러나 IMO로 인해 bash
의 버그입니다. ( ... )
배열 정의 내의 첫 번째 비 공백 문자가 [
에서 오류 메시지 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 )
댓글
- 1. 이것은
eval
를 사용합니다. 물론 ' 명령 주입의 위험이 있습니다. 하지만 '이 경우에 문제라고 생각하지 않습니다. ' 내 대답은 OP의 특정 & 아마도 검증 된 / 잘 알려진 입력 파일입니다. 2. " 확장을 인용하는 것을 잊었습니다 "-응? 뭐? ' 인용 문제가 보이지 않습니다. awk 코드는 배열의 키와 값을 모두 명시 적으로 인용합니다. 3. BTW, 거의 2 년 후 bash v4.4.19 (1) -release에서는 여전히 cmd-subst를 직접 사용할 수 없습니다. ' 해시 선언의 var :
declare -A array=( $(...) )
가 동일한 오류로 실패하므로 여전히 eval이 필요합니다. - @St é phaneChazelas 인용 문제가있는 경우 ' 그 이유와 방법을 설명해주십시오.이 질문 및 답변과 관련하여 유효한 / etc / passwd 스타일 입력을 사용하는 실제 예를 사용하는 것이 좋습니다. 일반적이고 명백한 " 가비지 데이터를 입력하면 ' 예측할 수없고 잠재적으로 위험한 결과를 얻을 수 있습니다. ".
- ' 일반적인
/etc/passwd
데이터. 다시 말해 보겠습니다. ⚠ 일반적인/etc/passwd
데이터에는 문제가 없지만 명령 주입 취약점을 구성 할 수 있으므로 임의의 데이터에는이 접근 방식을 사용해서는 안됩니다. 특히 데이터에 ',`
,"
, 백 슬래시,$
,*
,?
,[
, 공백 탭 또는 NUL 문자. - 인용 문제에 대해서는 예를 들어 bash / POSIX 셸에서 변수를 인용하는 것을 잊었을 때의 보안 의미를 참조하십시오.
- 이전 버전의 bash에는 ' a = (" $ x ")`는 하나의 요소가
$x
는$x
가[123]=qwe
(bash가 연관 배열을 지원하기 전)과 같을 때입니다.'의 진정한 bash는 연관 배열을a=("$x")
(여기서$x
는a=([$k]=$v)
구문과 함께[...]=
)로 시작해야하지만 다음을 지정하는 방법을 정의해야했습니다. ] 문자를 포함하는 키. 어쨌든 나는 그것을 버그라고 부르지 않고 디자인 결정 (여기서는 bash가 구문을 복사 한 곳에서 ksh에 의해 결정됨)이라고 부를 것입니다.
a> 및 거기에 링크 된 질문은 확장을 인용하지 않은 상태로 두는 것이 무엇을 의미하는지 확인합니다.
Answer
두 목록을 병합하는 대신 목록을 반환하여 단일 루프 (그리고 적절한 측정을 위해 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
Answer
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”로 분할됩니다.
, 구문은 ksh93
: array=([key1]=value1 [key2]=value2)
에서와 동일한 어색한 구문이므로 쉽게 출력을 얻을 수 없습니다. 다른 사람들이 보여준 것처럼 한 번에 하나의 단일 요소 할당을 수행하는 루프를 사용하는 것 이외의 연관 배열로 명령을 변환합니다.
bash
연관 배열 ( ksh93
또는 zsh
와는 반대로 키가 빈 문자열 (여기서는 문제가 아님)이 될 수 없다는 제한이 있습니다. 이번에 ksh93
와 공유되는 또 다른 제한은 키와 값 모두 NUL 바이트를 포함 할 수 없다는 것입니다 (여기서도 문제가되지 않음).
(연관 배열 지원은 다음과 같습니다. 처음부터 ksh93 (1993), 1998 년 zsh
(3.1.5-pws-3), 2009 년 bash
에 추가되었습니다 ( 4.0))
댓글
- '를 넣은 이유 \ n ' IFS에 두 번 입력 하시겠습니까?
- @rubystallion see edit