쉘은 한 번에 한 문자씩 읽어야 합니까(스크립트)?

쉘은 한 번에 한 문자씩 읽어야 합니까(스크립트)?

스크립트를 읽을 때 쉘은 파일, 파이프 또는 기타 소스(stdin?)에서 스크립트를 읽습니다. 일부 코너 조건에서는 입력을 찾지 못할 수도 있습니다(파일 위치를 이전 위치로 되돌릴 수 없음).

라고 한다read는 이스케이프되지 않은 개행 문자를 찾을 때까지 stdin을 한 번에 한 바이트씩 읽습니다.

쉘은 스크립트 입력에서 한 번에 한 문자씩 읽어야 합니까?
사용할 수 있는 추가 데이터 텍스트 파일이 아니라 스크립트를 의미합니다.

그렇다면 이것이 왜 필요한가요? 일부 사양에 정의되어 있습니까?

모든 쉘이 비슷하게 작동합니까? 어느 것이 아닌가?

답변1

쉘은 스크립트 파일이나 장치 설명자에서 읽습니다.

또는 파이프에서 검색할 수 없는 입력 fd를 얻는 가장 쉬운 방법일 것입니다.

쉘은 스크립트 입력에서 한 번에 한 문자씩 읽어야 합니까?

stdin에서 읽는 명령을 실행하는 스크립트를 지원하고 스크립트 자체의 행을 사용하여 입력을 얻으려는 경우.

이와 같이:

$ cat foo.sh
#!/bin/sh
line | sed -e 's/^/* /'
xxx
echo "end."

$ cat foo.sh | bash
* xxx
end.

line명령은 표준 입력( )에서 한 줄을 읽고 xxx, 쉘은 다른 줄을 명령으로 읽습니다. 이렇게 하려면 line너무 많은 입력을 읽지 않도록 주의해야 합니다. 그렇지 않으면 쉘에 다음 줄이 표시되지 않습니다. GNU 유틸리티 에서는 head -n1너무 많은 양을 읽습니다. 예를 들어 sedutil-linux의 유틸리티는 line한 번에 한 바이트씩 읽어서 이전 줄 바꿈을 읽지 않도록 주의합니다.

dash위 스크립트는 스크립트 전체를 한 번에 읽기 때문에 작동하지 않습니다 .

$ cat foo.sh | dash
* 
dash: 3: xxx: not found
end.

Dash와 Busybox는 전체 블록을 읽고, 제가 테스트한 다른 것(Bash, Ksh, mkshZsh)은 바이트 단위로 읽습니다.

이것은 상당히 복잡한 스크립트이며 예를 들어 다음과 같이 실행하면 제대로 작동하지 않습니다. bash foo.sh왜냐하면 이 경우 stdin스크립트 자체를 가리키지 않고 해당 xxx줄이 명령으로 처리되기 때문입니다. 스크립트 자체에 데이터를 포함하려면 여기에 있는 설명서를 사용하는 것이 더 나을 수 있습니다. 이는 sh bar.sh, sh < bar.sh또는 다음으로 실행될 때 모든 셸에서 작동합니다 cat bar.sh | sh.

$ cat bar.sh
#!/bin/sh
sed -e 's/^/* /' <<EOF
xxx
EOF
echo "end."

답변2

POSIX 호환 쉘의 경우 예입니다. Bash 개발자는 이렇게 말합니다.

POSIX에는 stdin에서 읽는 스크립트가 필요합니다. 인수로 제공된 스크립트에서 읽을 때 bash는 청크를 읽습니다.

그리고 실제로,POSIX 사양에 따르면이것은 (강조):

쉘이 표준 입력을 사용하고 표준 입력도 사용하는 명령을 호출하는 경우,인클로저는 다음을 보장해야 합니다.표준 입력파일 포인터는 읽은 명령 바로 뒤를 가리킵니다.명령 실행이 시작될 때.미리읽기 불가이런 식으로모든 문자호출 명령으로 읽으려는 문자는 쉘에서 사용되거나(쉘에서 해석되지 않음) 호출 명령으로 읽지 않은 문자는 쉘에서 표시되지 않습니다.

즉, (표준 입력 스크립트의 경우) 쉘은 한 번에 한 문자를 읽어야 합니다.

C 언어 환경에서 문자는 바이트입니다.

posh, mksh, lksh, attsh, yash, ksh, zsh 및 bash가 이 요구 사항을 충족하는 것 같습니다.

그러나 ash(busybox sh)와 dash는 그렇지 않습니다.

관련 정보