정규식 기반 명령의 출력을 축소하는 도구가 있습니까?

정규식 기반 명령의 출력을 축소하는 도구가 있습니까?

일부 애플리케이션 상태를 출력하는 명령이 있다고 가정해 보겠습니다. 이 명령은 영원히(또는 CC까지) 실행되며 애플리케이션 내부에서 어떤 일이 발생하면 한 줄을 출력합니다. 다음 형식으로 출력됩니다.

State N: Stuff M happened

collapse_prog나는 내가 제공하는 정규식을 기반으로 명령 출력 줄을 가져와 이전 상태를 덮어쓰는 프로그램을 원합니다 . 예를 들어, 입력 정규식이 State(\d+)라고 가정하고 다음 명령을 실행합니다.

my_command | collapse_prog

그리고 my_command출력

State 1: Stuff A happened
State 2: Stuff B happened

그러면 collapse_prog그대로 표시되어야 하는데 my_command다른 줄을 출력한 후에

State 1: Stuff C happened

그러면 collapse_prog다음과 같은 출력이 나와야 합니다.

State 1: Stuff C happened
State 2: Stuff B happened

이미 그런 프로그램이 있나요?

답변1

매우 기본적인 솔루션TxR분명하지 않은 말투:

$ program | txr stcoll.tl

어디 stcoll.tl:

(let ((states (hash)))
  (whilet ((line (get-line)))
    (when-match `State @s: @status` line
      (set [states s] status)
      (dohash (s status states)
        (put-line `State @s: @status`))
      (put-string `\e[@(len states)A`)
      (flush-stream *stdout*))))

작동 방식은 각 주의 최신 상태가 주 ID를 기준으로 해시 테이블에 저장된다는 것입니다. 상태 줄을 얻을 때마다 해시를 업데이트한 다음 인쇄합니다. 인쇄 후에는 ESC[<n>AVT100/ANSI 이스케이프 시퀀스를 사용하여 커서를 해당 행만큼 뒤로 이동합니다. 이는 터미널 창이 모든 상태에 대해 충분히 높다고 가정합니다. 이는 매우 간단한 대화형 보기 도구에 적합합니다.

더 복잡한 프로그램은 시간 초과(예: 1초) 후에 표준 입력을 폴링합니다. 또는 구성 가능합니다. 그런 다음 입력 루프를 통과할 때마다 행이 수신되는지 또는 시간 초과되는지 여부에 관계없이 해시가 변경되었는지 확인하고, 변경된 경우 마지막 새로 고침 이후 새로 고침 주기가 만료되었는지 여부를 확인합니다. 이 경우 디스플레이를 새로 고치십시오.

이러한 프로그램은 입력이 빠르게 도착할 때 디스플레이를 보다 효율적으로 업데이트합니다.

여기있어:

(let* ((states (hash))
       (last-time 0)
       (hash-touched nil)
       (unbuf-stdin (open-fileno (fileno *stdin*) "u"))
       (poll-list (vec (cons unbuf-stdin poll-in))))
  (while t
    (if (poll poll-list 1000)
      (let ((line (get-line unbuf-stdin)))
        (when-match `State @s: @status` line
          (set [states s] status
               hash-touched t))))
    (let ((now (time)))
      (when (and hash-touched (>= (- now last-time) 1))
        (dohash (s status states)
          (put-line `State @s: @status`))
        (put-string `\e[@(len states)A`)
        (flush-stream *stdout*)
        (set hash-touched nil
             last-time now)))))

프로그램이 뿜어져 나오더라도 1초 간격으로 업데이트가 됩니다. 이 프로그램을 사용하여 테스트 입력을 생성하고 있습니다. 20개 상태 중 하나를 무작위로 증가시키고 무작위 일시 중지와 함께 업데이트를 인쇄합니다.

(let* ((nstates 20)
       (states (vector nstates 0)))
  (while t
    (let ((choice (rand nstates)))
      (inc [states choice])
      (put-line `State @choice: @[states choice]`)
      (flush-stream *stdout*)
      (if (zerop (rand 4) )
        (usleep (rand 500000))))))

관련 정보