Bash 매뉴얼에서 read
내장 명령 에 대해
-d delim
의 첫 번째 문자는delim
개행 문자가 아닌 입력 행을 종료하는 데 사용됩니다.
(문자인 EOF와 일치하지 않는 한) 일치하지 않고 항상 전체 파일을 한 번에 읽도록 delim
문자 를 지정할 수 있습니까 ?read
read
감사해요.
답변1
bash
어쨌든 변수에 NUL 바이트를 저장할 수 없으므로 언제든지 다음을 수행할 수 있습니다 .
IFS= read -rd '' var < file
파일에 NUL 바이트가 없으면 첫 번째 NUL 바이트 또는 파일의 끝까지 파일의 내용을 저장합니다(정의에 따른 텍스트 파일(적어도 POSIX 정의에 따르면)은 NUL 바이트를 포함하지 않습니다).
또 다른 옵션은 파일 내용을 줄 배열(줄 구분 기호 포함)로 저장하는 것입니다.
readarray array < file
그런 다음 다음을 통해 참여할 수 있습니다.
IFS=; var="${array[*]}"
입력에 NUL 바이트가 포함되어 있으면 각 줄의 첫 번째 항목 이후의 모든 항목이 손실됩니다.
POSIX sh 구문에서는 다음을 수행할 수 있습니다.
var=$(cat < file; echo .); var=${var%.}
우리는 .
명령 대체가 모든 후행 줄 바꿈을 제거한다는 사실을 설명하기 위해 하나를 추가한 다음 제거했습니다.
파일에 NUL 바이트가 포함된 경우 동작은 구현마다 다릅니다. zsh
이를 유지하는 유일한 쉘입니다(또한 변수에 NUL 바이트를 저장할 수 있는 유일한 쉘이기도 합니다). bash
일부 다른 쉘은 이를 삭제하는 반면 다른 쉘은 이를 차단하고 첫 번째 NUL 발생 후 모든 것을 버립니다.
다음과 같이 일부 인코딩으로 파일 내용을 저장할 수도 있습니다.
var=$(uuencode -m - < file)
다음을 통해 다시 가져옵니다.
printf '%s\n' "$var" | uudecode
또는 매개변수에서 사용할 \0000
수 있도록 NUL로 인코딩합니다 (문자 집합 BIG5, GB18030, GBK, BIG5-HKCSC가 있는 로케일을 사용하지 않는다고 가정).printf %b
bash
var=; while true; do
if IFS= read -rd '' rec; then
var+=${rec//\\/\\\\}\\0000
else
var+=${rec//\\/\\\\}
break
fi
done < file
그런 다음:
printf %b "$var"
다시 가져.
답변2
대답은 일반적으로 "아니요"입니다. 왜냐하면 일반적으로 파일의 끝을 표시하는 실제 문자가 파일에 없기 때문입니다.
여기에 제안된 것과 같은 다른 접근 방식을 시도해 보는 것이 좋습니다.https://stackoverflow.com/questions/10984432/how-to-read-the-file-content-into-a-variable-in-one-go. 사용:
IFS="" contents=$(<file)
특히 우아합니다. Bash는 의 내용을 file
변수로 읽지 contents
만 Bash 변수는 NULL 바이트를 보유할 수 없습니다(C 스타일의 NULL 바이트로 끝나는 문자열의 내부 사용으로 인해). IFS=""
단어 분리를 비활성화하려면 내부 필드 구분 기호를 비워 두십시오(따라서 개행 문자 제거를 방지함).
참고: (평판 포인트 부족으로 인해) read
이 -N
옵션 사용을 제안하는 답변에 대해서는 언급할 수 없으므로 여기서 이 답변은 정의에 따라 파일 크기를 알 수 없기 때문에 있는 그대로 작동한다고 보장되지 않습니다. 미리.
답변3
에서는 (문자 수) 옵션을 bash
사용합니다 .-N
read -rN 40000000 foo
-r
파일에 백슬래시 이스케이프 문자가 포함되도록 하려면 이 옵션을 무시하십시오.
에서 help read
:
-N nchars return only after reading exactly NCHARS characters, unless EOF is encountered or read times out, ignoring any delimiter
EOF
문자가 아니라 상태: a read
(쉘 내장이 아닌 시스템 호출)가 0 길이를 반환했습니다. 그러나 다른 함수는 모든 문자 세트의 유효한 문자와 충돌할 수 없는 (-1) 값의 정수를 getchar()
편리하게 반환합니다 . 따라서 EOF
일부 이전 운영 체제에서는 파일 시스템 메타데이터의 전체 블록만 추적하기 때문에 EOF 마커(일반적으로 )를 사용한다는 ^Z
사실로 인해 혼란이 더욱 가중됩니다 .
이상하게도 read -N0
"느린 후루룩 소리"를 내는 것 같습니다(전체 파일을 같은 방식으로 읽지만 각 문자에 대해 시스템 호출을 수행합니다). 의도한 기능인지는 잘 모르겠습니다 ;-)
strace -fe trace=read ./bash -c 'echo yes | read -N0'
...
[pid 8032] read(0, "y", 1) = 1
[pid 8032] read(0, "e", 1) = 1
[pid 8032] read(0, "s", 1) = 1
[pid 8032] read(0, "\n", 1) = 1
[pid 8032] read(0, "", 1) = 0
bash
내장에서 사용하는 버퍼는 read
128바이트에 불과하므로 대용량 파일을 읽는 데 사용하면 안 됩니다. 또한 파일이 utf-8을 많이 사용하는 경우 이를 사용해야 합니다 LC_CTYPE=C read ...
. 그렇지 않으면 bash
128바이트 읽기와 바이트 단위 읽기가 번갈아 수행되므로 속도가 느려집니다.