다음을 포함하는 ‘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’가있는 줄이 나타날 때까지 읽고 인쇄 한 다음 중지합니다. 첫 번째 경우 (두 번째는 아님), 고양이는 나머지를 읽고 인쇄합니다.
누군가이 행동의 차이 뒤에 어떤 현상이 있는지 설명 할 수 있습니까?
또한 Ubuntu 16.04 및 Centos 6에서는이 방식으로 작동하지만 Centos 7에서는 명령이 ‘zzz’를 인쇄하지 않습니다.
답변
입력 파일 인 경우 시크 하거나 (일반 파일의 읽기와 같은) 되지 않은 시크 (파이프에서 읽기 등) sed
(및 기타 표준 유틸리티) 다른 (읽기 동작합니다 INPUT FILES
섹션 이 링크를 ).
문서에서 인용 :
표준 유틸리티가 탐색 가능한 입력 파일을 읽고 파일 끝에 도달하기 전에 오류없이 종료되는 경우, 유틸리티는 열린 파일 설명의 파일 오프셋이 유틸리티가 처리 한 마지막 바이트 바로 위에 위치하는지 확인해야합니다.
그래서 :
(sed '/y/ q'; echo aaa; cat) < test
sed
q
EOF에 도달하기 전에 uit 명령을 수행 하여 zzz
줄의 시작 부분에서 파일 오프셋을 남겨 두어 나머지 줄 cat
을 계속 인쇄 할 수 있습니다 (GNU sed는 어떤 조건에서 POSIX 호환이 아닙니다 (아래 참조)).
그리고 문서에서 계속 :
찾을 수없는 파일의 경우 해당 파일에 대한 열린 파일 설명의 파일 오프셋 상태는 지정되지 않습니다.
이 경우 동작은 지정되지 않습니다. 대부분의 표준 도구, 포함 sed
은 가능한 한 많이 입력을 소비합니다. 파일 오프셋을 복원하지 않고 yyy
행을 읽습니다 . q
그래서 아무것도 남지 않습니다 cat
.
GNU sed
는 표준을 준수하지 않으며 시스템의 stdio 구현 및 glibc 버전에 따라 다릅니다.
$ (gsed '/y/ q'; echo aaa; cat) < test
xxx
yyy
aaa
여기서 결과는 Mac OSX 10.11.6, 가상 머신 Centos 7.2-glibc 2.17, Ubuntu 14.04-glibc 2.19에서 얻은 것으로, CEPH 백엔드를 사용하여 Openstack에서 실행됩니다.
이러한 시스템에서 -u
옵션을 사용 하여 표준 동작을 달성 할 수 있습니다 .
(gsed -u '/y/ q'; echo aaa; cat) </tmp/test
그리고 파이프 :
$ cat test | (gsed -u '/y/ q'; echo aaa; cat)
xxx
yyy
aaa
zzz
한 sed
번에 1 바이트를 읽어야 하기 때문에 성능이 크게 비효율적 입니다. 의 부분 출력 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
...