다음 내용으로 "test"라는 테스트 파일을 만들었습니다.
xxx
yyy
zzz
나는 다음 명령을 실행했습니다.
(sed '/y/ q'; echo aaa; cat) < test
알겠어요:
xxx
yyy
aaa
zzz
그런 다음 나는 다음을 실행했습니다.
cat test | (sed '/y/ q'; echo aaa; cat)
그리고 얻다:
xxx
yyy
aaa
질문
sed
"y" 줄이 나타날 때까지 읽고 인쇄한 다음 중지합니다. 첫 번째 경우에는 cat이 나머지 내용을 읽고 인쇄하지만 두 번째 경우에는 그렇지 않습니다.
이러한 행동 차이 뒤에 숨어 있는 현상이 무엇인지 설명할 수 있는 사람이 있습니까?
또한 Ubuntu 16.04 및 Centos 6에서는 이런 방식으로 작동하지만 Centos 7에서는 두 명령 모두 "zzz"를 인쇄하지 않는 것으로 나타났습니다.
답변1
입력 파일이 다음과 같을 때탐색 가능한(일반 파일에서 읽는 것과 같은) 또는검색할 수 없음(파이프에서 읽는 것과 유사) sed
(및 기타 표준 유틸리티)는 다르게 작동합니다 INPUT FILES
.이 링크).
인용 문서:
표준 유틸리티가 검색 가능한 입력 파일을 읽고 파일 끝에 도달하기 전에 오류 없이 종료되는 경우 유틸리티는 열린 파일 설명의 파일 오프셋이 유틸리티가 처리한 마지막 바이트 뒤에 올바르게 위치하는지 확인해야 합니다.
그래서:
(sed '/y/ q'; echo aaa; cat) < test
sed
uit 명령은 EOF에 도달하기 전에 실행 q
되므로 줄의 시작 부분에 파일 오프셋을 남겨두고 나머지 줄을 계속 인쇄할 수 있습니다(GNU sed는 어떤 경우에는 POSIX와 호환되지 않습니다. 아래 참조) zzz
.cat
그리고 문서를 계속 진행하면 다음과 같습니다.
검색 불가능한 파일의 경우 파일의 열린 파일 설명에 파일 오프셋 상태가 지정되지 않습니다.
이 경우 동작은 지정되지 않습니다. 대부분의 표준 도구(포함)는 sed
가능한 한 많은 입력을 소비합니다. yyy
라인 을 읽고 전달하며 q
파일 오프셋을 복원하지 않으므로 아무것도 남지 않습니다 cat
.
GNU는 sed
표준을 준수하지 않으며 시스템의 stdio 구현 및 glibc 버전에 따라 다릅니다.
$ (gsed '/y/ q'; echo aaa; cat) < test
xxx
yyy
aaa
여기의 결과는 CEPH 백엔드가 있는 Openstack에서 실행되는 Mac OSX 10.11.6, 가상 머신 Centos 7.2 - glibc 2.17, Ubuntu 14.04 - glibc 2.19에서 얻은 것입니다.
이러한 시스템에서는 -u
옵션을 사용하여 표준 동작을 달성할 수 있습니다.
(gsed -u '/y/ q'; echo aaa; cat) </tmp/test
파이프의 경우:
$ cat test | (gsed -u '/y/ q'; echo aaa; cat)
xxx
yyy
aaa
zzz
sed
한 번에 한 바이트씩 읽어야 하므로 성능이 매우 비효율적입니다 . 부분 출력 strace
:
$ strace -fe read sh -c '{ sed -u "/y/q"; echo aaa; cat; } <test'
...
[pid 5248] read(3, "", 4096) = 0
[pid 5248] read(0, "x", 1) = 1
[pid 5248] read(0, "x", 1) = 1
[pid 5248] read(0, "x", 1) = 1
[pid 5248] read(0, "\n", 1) = 1
xxx
[pid 5248] read(0, "y", 1) = 1
[pid 5248] read(0, "y", 1) = 1
[pid 5248] read(0, "y", 1) = 1
[pid 5248] read(0, "\n", 1) = 1
yyy
...