나는 아래 패턴을 사용하여 bash 스크립트의 터미널에 여러 줄의 메시지를 인쇄했습니다.
read -d '' message <<- EOF
this is a
mulitline
message
EOF
echo "$message"
이것은 작동하고 있었습니다. 며칠 전까지만 해도 모드 작동이 중단되었습니다. 작동을 멈춘다는 것은 bash가 스크립트에서 이러한 구분 기호 표현을 발견했을 때 아무 것도 하지 않는 것 같고 출력이 없다는 것을 의미합니다.
지난 며칠 동안 제가 생각할 수 있는 유일한 변화는 스크립트가 실행되는 환경이 "전체" 설치가 아니라 Ubuntu 14.04 라이브 USB라는 것입니다. 그런 다음 스크립트 명령문 이전에
heredoc을 이동하면 다시 작동하기 시작한다는 것을 알았습니다 . set -o errexit
즉, 이것은 작동하지 않습니다
#!/bin/bash
set -o errexit
read -d '' message <<- EOF
this is a
mulitline
message
EOF
echo "$message"
결과: (아무것도)
하지만 이건실제로 작동한다
#!/bin/bash
read -d '' message <<- EOF
this is a
mulitline
message
EOF
echo "$message"
결과
$ sudo ./script.sh
this is a
mulitline
message
- 배쉬 --버전-
GNU bash, version 4.3.11(1)-release (i686-pc-linux-gnu)
답변1
read
구분 기호를 찾을 수 없으면 0이 아닌 종료 상태가 반환됩니다. 구분 기호를 빈 문자열로 설정한 후 일반적으로 텍스트 파일에서 찾을 수 없는 NUL 바이트를 구분 기호로 사용합니다.
답변2
EOF(파일 끝) 표시에 도달하면 읽기 명령의 종료 코드는 1입니다. 이 특별한 경우에는 -d
구분 기호가 비어 있을 때 항상 발생합니다 ''
. 여기서 소스 스트림은 \0을 포함할 수 없는 구분된 문서입니다.
$ read -d '' message <<-_ThisMessageEnds_
> this is a
> multi line
> message
> _ThisMessageEnds_
$ exitval=$?
$ echo "The exit val was $exitval"
The exit val was 1.
종료 값은 오류(0 아님)이며, 이를 통해 AND/OR 구문을 사용하여 스크립트 종료를 방지할 수 있습니다.
read -d '' message <<-_ThisMessageEnds_ || echo "$message"
this is a
multi line
message
_ThisMessageEnds_
이렇게 하면 메시지가 콘솔로 전송되지만 콘솔 종료는 방지됩니다 errexit
.
하지만 앞으로는 축소할 예정이므로 그냥 사용해 보는 것은 어떨까요?
cat <<-_ThisMessageEnds_
this is a
mulitline
message
_ThisMessageEnds_
읽기 명령이 더 빠르게 실행되고, 변수가 필요하지 않으며, 종료 코드에 오류가 없고, 유지 관리할 코드가 적습니다.
답변3
read -d '' message
이스케이프되지 않은 첫 번째 NUL 문자(하나를 추가하지 않았기 때문에 -r
) 또는 입력의 끝까지 표준 입력을 읽고 $IFS
백슬래시 문자로 처리된 데이터를 $message
구분 기호 없이 저장합니다.
입력에 이스케이프 처리되지 않은 구분 기호가 없으면 read
종료 상태는 0이 아닙니다. 완전 종료 레코드를 읽으면 0(성공)만 반환됩니다.
NUL로 구분된 레코드(예: 출력)를 처리하는 데 가장 유용합니다 ( 나중에 구문이 find -print0
필요하더라도 ).IFS= read -rd '' record
read
성공적인 반환을 위해서는 이 문서에 NUL 구분 기호를 포함해야 합니다 . 그러나 bash
이 문서에서 NUL 문자를 제거하는 것은 불가능합니다( yash
여기 문서에 NUL이 포함되어 있을 때 무한 루프에 빠지는 것처럼 보이는 첫 번째 NUL 또는 ksh93 이후의 모든 항목을 제거하는 것보다 적어도 낫습니다).
zsh
문서에 NUL을 포함하거나 변수에 저장하거나 내장 함수/함수에 NUL 문자를 인수로 전달할 수 있는 유일한 쉘입니다. 에서는 zsh
다음을 수행할 수 있습니다.
NUL=$'\0'
IFS= read -d $NUL -r var << EOF
1
2
3$NUL
EOF
( . 와 같은 NUL 구분 기호로 도 zsh
이해 되지만 NUL 바이트는 명령줄에서 지원되지 않으므로 like in 에 빈 인수를 전달합니다 .)read -d ''
bash
read -d $'\0'
bash
read
read -d ''
bash
(다음에 추가 줄바꿈이 있다는 점에 유의하세요 $NUL
)
bash
다양한 문자를 사용할 수 있습니다 .
ONE=$'\1'
IFS= read -d "$ONE" -r var << EOF
1
2
3$ONE
EOF
하지만 다음과 같이 할 수도 있습니다.
var=$(cat <<EOF
message
here
EOF
)
여전히 NUL 문자는 허용되지 않습니다. 그러나 이것은 표준 코드이므로 zsh/bash 특정 코드에 의존할 필요가 없습니다 read -d
. 또한 모든 후행 줄 바꿈을 제거하므로 ksh93
내장 기능이 활성화되지 cat
않으면 추가 프로세스와 명령이 생성됩니다 .
답변4
사용 set -o errexit
하고 스크립트가 중단되면 뭔가 잘못되었음을 의미합니다.
여기는read
, 입력 내용을 올바르게 읽을 수 없습니다.
에서 bash
사용할 read -d ''
때read
내장\0
널 문자는 줄 종결자로 사용됩니다 . 따라서 \0
입력에 아무것도 없으면 read
모든 입력이 변수로 읽혀지고 message
0이 아닌 종료 상태가 반환되어 오류를 나타냅니다.
$ while read -d '' line; do echo "$line"; done < <(printf '1')
다음과 같은 경우에는 아무것도 인쇄하지 않습니다.
$ while read -d '' line; do echo "$line"; done < <(printf '1\0')
1
당신을 위한 1
.
read
또한 EOF에 도달하면 0이 아닌 상태를 반환하지만 이는 루프 read
와 함께 사용할 때 while
읽을 입력이 더 이상 없으므로 while
루프가 종료될 수 있음을 나타내는 데 사용됩니다. 이것은 귀하의 질문과 관련이 없습니다.