출력을 리디렉션하려고 하면 cut
항상 비어 있는 것 같습니다. 리디렉션하지 않으면 출력이 예상대로 터미널에 나타납니다. OS X 10.10 및 Linux 4.1.6에서도 마찬가지입니다.
이것은 작동합니다:
root@karla:~# nc 10.0.2.56 30003
[...] lots of lines [...]
이것은 작동합니다:
root@karla:~# nc 10.0.2.56 30003 | cat
[...] lots of lines [...]
이것은 작동합니다:
root@karla:~# nc 10.0.2.56 30003 | cut -d, -f 15,16
[...] lots of lines [...]
이것은 아니다
root@karla:~# nc 10.0.2.56 30003 | cut -d, -f 15,16 | cat
[nothing]
이게 또하다
root@karla:~# cat messung1 | cut -d, -f15,16 | cat
[...] lots of lines [...]
cat
이는 after 에만 국한되지 않습니다 cut
. grep
, tee
표준 리디렉션을 사용해 >
도 작동하지 않습니다.
무슨 문제가 있었나요?
답변1
출력이 없는 것이 아니라 덩어리로 출력됩니다.
많은 프로그램과 마찬가지로 cut
해당 출력은 더 이상 터미널이 아닐 때 버퍼링됩니다. 즉, 버퍼가 가득 찼을 때만 데이터를 씁니다. 일반적으로 YMMV는 약 4 또는 8KiB입니다.
다음을 비교하여 이를 쉽게 확인할 수 있습니다.
(echo foo; sleep 1; echo bar) | cut -c2-
그리고:
(echo foo; sleep 1; echo bar) | cut -c2- | cat
첫 번째 경우에는 1초 후에 cut
출력이 출력 oo\n
되는 ar\n
반면, 두 번째 경우에는 oo\nar\n
1초 후에 출력이 차단됩니다. 즉, 입력의 끝을 확인하고 종료 시 출력을 플러시하는 경우입니다.
귀하의 경우 stdin은 nc
연결이 닫힐 때만 입력의 끝을 볼 수 있으므로 쓸 데이터가 4KiB 축적된 후에만 출력을 시작합니다.
이 문제를 해결하기 위해 여러 가지 방법을 사용할 수 있습니다.
GNU 또는 FreeBSD 시스템에서는
stdbuf
특정 명령의 버퍼링 동작을 조정할 수 있는 유틸리티를 사용할 수 있습니다(stdio 버퍼링 동작을 사전 구성하기 위해 LD_PRELOAD 해킹을 사용하기 때문에 모든 명령에 대해 작동하지는 않습니다).... | stdbuf -oL cut -d, -f15,16 | cat
cut
표준 출력에서 라인 기반 버퍼링을 수행하도록 지시합니다 .GNU와 같은 일부 명령에는
grep
버퍼링에 영향을 미치는 옵션이 있습니다. (--line-buffered
GNU의 경우grep
).pseudo-tty 래퍼를 사용하여 명령의 표준 출력을 터미널에 강제로 보낼 수 있습니다. 그러나 대부분의 이러한 솔루션에는 몇 가지 단점과 제한 사항이 있습니다.
unbuffer
expect
예를 들어, 이러한 문제를 해결하기 위해 자주 언급되는 스크립트에는 버그가 많이 있습니다.잘 작동하는 것은 다음
socat
과 같이 사용할 때입니다.... | socat -u 'exec:"cut -d, -f15,16",pty,raw' -
버퍼링되지 않은 출력을 지원하는 고급 텍스트 처리 도구로 텍스트 유틸리티를 대체할 수 있습니다.
awk
예를 들어, GNU에는fflush()
출력을 플러시하는 기능이 있습니다. 따라서 귀하는 다음cut -d, -f15,16
과 같이 작성할 수 있습니다.awk -F, -vOFS=, '{print $15,$16;fflush()}'
awk
해당 기능이 누락된 경우 해당 기능을 대신fflush()
사용할 수 있습니다system("")
. 이는 일반적으로 명령을 실행하는 명령입니다. 여기서는 빈 명령을 실행하지만 실제로는awk
명령을 실행하기 전에 명령의 표준 출력을 플러시하는 데 사용합니다.또는 다음을 사용할 수 있습니다
perl
.perl -F, -lane 'BEGIN{$,=",";$|=1} print @F[14..15]'