"read"가 파일 전체를 한번에 읽을 수 있도록 "read"의 "구분자" 역할을 하는 문자가 있나요?

"read"가 파일 전체를 한번에 읽을 수 있도록 "read"의 "구분자" 역할을 하는 문자가 있나요?

Bash 매뉴얼에서 read내장 명령 에 대해

-d delim의 첫 번째 문자는 delim개행 문자가 아닌 입력 행을 종료하는 데 사용됩니다.

(문자인 EOF와 일치하지 않는 한) 일치하지 않고 항상 전체 파일을 한 번에 읽도록 delim​​문자 를 지정할 수 있습니까 ?readread

감사해요.

답변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 %bbash

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내장에서 사용하는 버퍼는 read128바이트에 불과하므로 대용량 파일을 읽는 데 사용하면 안 됩니다. 또한 파일이 utf-8을 많이 사용하는 경우 이를 사용해야 합니다 LC_CTYPE=C read .... 그렇지 않으면 bash128바이트 읽기와 바이트 단위 읽기가 번갈아 수행되므로 속도가 느려집니다.

관련 정보