uniq를 사용하여 파이프라인에서 인접한 행 필터링

uniq를 사용하여 파이프라인에서 인접한 행 필터링

다음 명령을 사용하여 테마 변경 사항을 모니터링하려고 합니다.

dbus-monitor --session "interface='org.freedesktop.portal.Settings', member=SettingChanged" | grep -o "uint32 ."

이제 출력은 다음과 같습니다.

uint32 0
uint32 0
uint32 1
uint32 1
uint32 0
uint32 0
uint32 1
uint32 1

이 출력은 테마 전환에서 비롯됩니다. 어떤 이유로 주제 알림이 두 번 나타납니다. 이제 uniq다음과 같이 하나의 항목만 남도록 파이프하고 싶습니다 .

uint32 0
uint32 1
uint32 0
uint32 1

그러나 끝에 추가하면 uniq더 이상 출력이 생성되지 않습니다.

dbus-monitor --session "interface='org.freedesktop.portal.Settings', member=SettingChanged" | grep -o "uint32 ." | uniq

에서 man uniq:

INPUT(또는 표준 입력)에서 인접한 일치하는 라인을 필터링하고 OUTPUT(또는 표준 출력)에 씁니다.

uniq적어도 마지막 출력 라인은 인접한 라인을 감지하기 위해 버퍼링되어야 합니다. 버퍼링하여 파이프를 따라 전달할 수 없는 이유는 없습니다. 제안된 대로 행 버퍼링을 조정해 보았습니다.여기하지만 결과는 여전히 나에게 동일합니다.

dbus-monitor --session "interface='org.freedesktop.portal.Settings', member=SettingChanged" | grep -o "uint32 ." | stdbuf -oL -i0 uniq

답변1

이는 많은 도구의 일반적인 동작이며 함수 작업을 통해 기본 표준 C 라이브러리 동작에서 상속됩니다.입력/출력 스트림( fopen(3), fwrite(3)...). 이는 문서화되어 있습니다 setvbuf(3)(또는 더 이상 사용되지 않는 변형). 여러 *nix가 모두 같은 말을 했습니다.*두번째에스,솔라리스,GNU/리눅스..., 하지만POSIX구체적인 내용이 없으면 ISO/IEC 9899는 너무 어렵습니다.GNU는 말한다:

새로 열린 스트림은 일반적으로 완전히 버퍼링되지만 한 가지 예외는 대화형 장치(예: 터미널)에 연결된 스트림이 처음에 라인 버퍼링된다는 것입니다.

(반품,표준 에러일반적으로 모든 구현에서 버퍼링되지 않습니다. 이 Q&A에서는 중요하지 않습니다. )

따라서 대부분의 텍스트 필터링 명령(모두는 아님, 예를 들어 cat이 동작이 없음)의 경우 파이프라인의 마지막 명령이 아닌 한 해당 출력은 더 이상 라인 버퍼링되지 않으며 개행은 즉시 전송을 트리거하지 않습니다. 다음 주문에서 처리할 데이터입니다.


여기관련 명령은 uniq아니지만grep출력이 터미널에서 비터미널로 전환되기 때문입니다. GNU에는 grep이 동작을 변경할 수 있는 옵션이 있습니다:--line-buffered:

--line-buffered

출력 시 라인 버퍼링을 사용합니다. 이로 인해 성능이 저하될 수 있습니다.

명령에 동작을 선택하는 특정 옵션이 없는 경우에도 명령을 사용할 수 있습니다.stdbufsetvbuf(3)다음을 사용하여 동작을 변경합니다.LD_PRELOAD기구. 파이프 끝에 있지 않은 명령에 대한 라인 버퍼링 동작을 복원하려면 명령 앞에 stdbuf -oL.

OP의 상황:

dbus-monitor --session "interface='org.freedesktop.portal.Settings', member=SettingChanged" |
    grep --line-buffered -o "uint32 ." | uniq

또는 이 grep명령에 특정 옵션이 없는 경우:

dbus-monitor --session "interface='org.freedesktop.portal.Settings', member=SettingChanged" |
    stdbuf -oL grep -o "uint32 ." | uniq

두 경우 모두 uniq파이프라인 끝에 있는 경우 기본 동작을 조정할 필요가 없습니다.

나중에 파이프가 확장되어 uniq더 이상 끝에 있지 않아 더 이상 터미널로 출력되지 않는 경우에도 동작이 변경되고 동일한 처리가 필요합니다. 예를 들어 uniq터미널에서 명령 의 별도 라인 버퍼링 동작은 다음과 같습니다.

uniq

전체 버퍼링으로 변경:

uniq | cat

그러나 다음을 통해 행 버퍼링으로 되돌릴 수 있습니다.

stdbuf -oL uniq | cat

관련 정보