읽기 -a 배열 -d '\n' < foo, 종료 코드 1

읽기 -a 배열 -d '\n' < foo, 종료 코드 1

내가 실행하려고 하면

read -a fooArr -d '\n' < bar

종료 코드는 1입니다. 비록 그것이 내가 원하는 것을 수행하더라도 각 행을 bar배열의 요소 에 넣습니다 fooArr(bash 4.2.37 사용).

왜 이런 일이 발생하는지 설명할 수 있는 사람이 있나요?


아래와 같이 이 문제를 해결하기 위한 다른 방법을 찾았으므로 이는 제가 요구하는 것이 아닙니다.

for ((i=1;; i++)); do
    read "fooArr$i" || break;
done < bar

또는

mapfile -t fooArr < bar

답변1

설명해야 할 것은 종료 코드가 아니라 명령이 작동하는 것 같다는 것입니다.

'\n'백슬래시 \와 문자 라는 두 문자입니다 n. 당신이 필요하다고 생각하는 것은 $'\n'그것이 개행 문자라는 것입니다(하지만 그것도 정확하지 않습니다. 아래를 참조하십시오).

-d옵션은 다음을 수행합니다.

  -d delim  continue until the first character of DELIM is read, rather
            than newline

따라서 해당 옵션이 없으면 read개행 문자를 읽고 $IFS문자를 구분 기호로 사용하여 행을 단어로 분할한 다음 해당 단어를 배열에 넣습니다. 을 지정하는 경우 -d $'\n'줄 구분 기호를 줄 바꿈으로 설정하면 다음을 수행할 수 있습니다.똑같은 것. 설정이란 -d '\n'의 첫 번째 문자인 첫 번째 백슬래시(그러나 다시 아래 참조)까지 읽는다는 의미입니다 delim. 파일에 백슬래시가 없으므로 read파일 끝에서 종료됩니다.

Exit Status:
The return code is zero, unless end-of-file is encountered, read times out,
or an invalid file descriptor is supplied as the argument to -u.

이것이 종료 코드가 1인 이유입니다.

명령이 작동한다고 생각하면 파일에 공백이 없다고 결론을 내릴 수 있습니다. 따라서 백슬래시를 찾으려는 헛된 희망으로 전체 파일을 읽은 후에는 줄 바꿈을 포함하여 공백(기본값) read으로 구분됩니다. $IFS. 따라서 각 행(또는 행에 여러 단어가 포함된 경우 각 단어)이 배열에 저장됩니다.

백슬래시 도난 사건

이제 파일에 백슬래시가 포함되어 있지 않다는 것을 어떻게 알 수 있습니까? -r다음 대상에 플래그를 제공 하지 않았기 때문입니다 read.

  -r                do not allow backslashes to escape any characters

따라서 파일에 백슬래시가 있는 경우 두 개가 연속되지 않는 한 제거됩니다. 물론 read종료 코드가 1이라는 증거가 있는데, 이는 백슬래시를 찾지 못했음을 의미하므로 연속된 두 개가 없었다는 것을 의미합니다.

주요 요점

Bash는 예외 없이 거의 모든 명령 뒤에 숨겨진 함정이 없다면 Bash가 아닐 것입니다 read. 다음은 몇 가지입니다:

  1. 백슬래시 이스케이프 시퀀스는 지정 -r하지 않으면 read해석됩니다 . 이것이 실제로 원하는 것이 아니라면(가끔 그럴 때도 있지만 가끔씩만) -r입력에 백슬래시가 있는 드문 경우에 문자가 사라지지 않도록 지정하는 것을 기억해야 합니다.

  2. 종료 코드 1을 반환한다고 해서 read실패했다는 의미는 아닙니다. 줄 종결자를 찾는 것 외에는 성공했을 가능성이 높습니다. 따라서 다음과 같은 루프에 주의하세요. 드문 경우지만 마지막 줄 끝에 개행 문자가 없기 때문에 while read -r LINE; do something with LINE; done 마지막 줄을 처리할 수 없습니다.do something

  3. read -r LINE백슬래시는 유지되지만 선행 또는 후행 공백은 유지되지 않습니다.

답변2

이는 예상되는 동작입니다.

파일 끝이 발견되지 않는 한 반환 코드는 0입니다. [...]

start cmd:> echo a b c | { read -a testarray; echo $?; }
0

start cmd:> echo -n a b c | { read -a testarray; echo $?; }
1

관련 정보