IFS 루프를 사용하여 파일을 읽는 것은 배열을 사용하지 않는 경우에만 작동합니다.

IFS 루프를 사용하여 파일을 읽는 것은 배열을 사용하지 않는 경우에만 작동합니다.

다음 코드를 사용하여 파일을 배열로 읽어 보려고 합니다.

GROUPS=()

while IFS=: read -r g1 g2 g3 g4
do
    GROUPS+=("$g3")
    echo "$g3"
done < /etc/group

이것은 작동하지 않고 아무것도 출력하지 않습니다. 그러나 에코를 그대로 두면 파일의 내용이 인쇄됩니다. 배열에 추가하라는 명령이 루프 어딘가에서 발생하는 한 아무 것도 인쇄되지 않습니다. 다른 파일에도 아무 문제 없이 이 작업을 수행할 수 있기 때문에 이것이 이상해 보입니다.

원인이 무엇인지 아시나요? bash -x로 확인했는데 문제가 되는 명령이 있을 때 루프에 들어가지도 않습니다.

또한 관련성이 있는 경우 루트로 실행합니다.

답변1

bash불행하게도 이미 자체적으로 예약되어 있는 배열의 이름을 선택하셨습니다 .읽기 전용이므로 변경할 수 없습니다.

그룹

현재 사용자가 속한 그룹 목록을 포함하는 배열 변수입니다. GROUPS에 대한 할당이 잘못되었으며 오류 상태가 반환됩니다. GROUPS가 설정되지 않으면 이후에 재설정되더라도 특수 속성이 손실됩니다.

다른 이름을 사용하면 코드가 작동합니다.

답변2

루프를 사용하여 bash에서 이 작업을 완전히 수행하는 방법에 대한 답변이 이미 있습니다 while ... read .... bash에서만 이 작업을 수행하는 것이 최악의 방법 중 하나라고 제안하고 싶습니다.

또한 /etc/group파일은 그룹 데이터의 가능한 소스 중 하나일 뿐이므로 읽는 것 자체는 좋은 생각이 아닙니다. 다른 소스에는 LDAP, Active Directory, winbind, NIS, mysql, pgsql, Berkeley db 파일, 의 추가 그룹 파일이 포함될 수 있습니다 libnss-extrausers. 더 많은).

대신 출력을 사용하십시오 getent group.

이 시도:

g=( $(getent group | awk -F: '{print $3}') )

또는

g=( $(getent group | cut -d: -f3) )

awk이 방법은 정규식이나 고정 텍스트 검색 및/또는 $1 == groupname또는 같은 기타 선택 기준과 $3 >= 500 && $3 <= 1000결합하려는 경우 특히 유용합니다 .

예를 들어 디버깅을 위해 다음과 같이 배열의 그룹을 인쇄할 수 있습니다 g.

# all on one line
echo "${g[@]}"

# one element per line
printf "%s\n" "${g[@]}"

# in a format that can be re-used to define the variable in another
# bash shell or script.
declare -p g

저는 특히 declare -p디버깅을 좋아합니다. 변수 이름(예: 와 같은 것 echo "foo='$foo'")뿐만 아니라 배열 변수의 배열 인덱스도 표시하며 모든 것이 적절하게 인용되고 백슬래시가 이스케이프됩니다.

$ g=( $(getent group | awk -F: '$1 ~ /my/ {print $1}') )
$ declare -p g
declare -a g='([0]="mysql" [1]="mythtv")'

BTW는 bash 및 ksh와 같은 다른 쉘에서 작업하는 것과 동의어입니다 typeset.declare

관련 정보