파이프를 올바르게 버퍼링 해제하는 방법은 무엇입니까?

파이프를 올바르게 버퍼링 해제하는 방법은 무엇입니까?

다양한 답변을 따라가려고 노력 중이에요이것,이것그리고이것스레드가 있지만 파이프가 여전히 버퍼링된 것처럼 보입니다. 시도해 볼 수 있는 예는 다음과 같습니다.

unbuffer sh -c 'echo -n test; sleep 1; echo; sleep 1; echo -n hello; sleep 1; echo' | grep .

위 명령은 즉시 인쇄 test한 다음 두 번째 인쇄 hello하고 1초 후에 다시 인쇄해야 합니다. 대신 1초의 지연이 발생하고 test얼마 후- 두 번째 지연 후에 hello명령이 종료됩니다.

여기서 내가 노력하고 있다는 점에 유의하십시오.완전히버퍼링을 제거하면 --line-buffered옵션이 grep도움이 되지 않습니다. 그렇다면 실제로 이 파이프를 어떻게 버퍼링 해제합니까?

답변1

grep출력됩니다철사패턴과 일치하므로 전체 줄을 읽을 때까지(또는 파일의 끝, 마지막 줄이 끝나지 않으면 동작은 구현에 따라 다름)까지 아무것도 출력할 수 없습니다.

그래서:

(echo -n foo; sleep 1; echo bar) | grep .

때문에가 아니라echo 출력을 버퍼링. 그러나 실제로는 그렇지 않습니다. 일단 종료되면 어떻게 가능합니까? 이는 줄 끝이 기다리고 있기 때문입니다 grep(곧 제공될 예정이며 두 번째 파일 끝 문자가 뒤따름 echo).

원하는 대로 수행하려면 행당 시간 초과가 있는 행을 읽어야 합니다(예: 사용 bash).

(echo -n foo; sleep 1; echo bar) |
  while true; do
    TMOUT=0.1 IFS= read -r line; ret=$?
    if [ "$(kill -l "$ret")" = ALRM ]; then
      [ -n "$line" ] || continue
      ors=
    elif [ "$ret" -eq 0 ]; then
      ors=$'\n'
    elif [ -z "$line" ]; then
      break
    fi
    [[ $line =~ . ]] && printf %s "$line$ors"
  done

(적어도 0.1초마다 루프에서 패스를 받으세요).

관련 정보