grep 대화형 프로그램

grep 대화형 프로그램

관련 없는 오류 메시지를 많이 출력하여 고객에게 혼란을 주는 대화형 셸형 프로그램이 있습니다. 각 오류 메시지는 "%"로 시작하는 전체 메시지 줄입니다.

따라서 이를 제거하는 쉬운 방법은 다음과 같습니다.

command | grep -v "^%[^\n]*$"

명령은 쉘과 유사한 프로그램입니다.

하지만 문제는 개행 문자를 받은 후에만 사용자에게 아무것도 출력한다는 것입니다. 따라서 사용자가 프로그램에 무엇이든 입력하면 Enter 키를 누를 때까지 입력된 내용에 대한 피드백이 없습니다.

이와 같은 비라인 기반 작업을 수행할 수 있는 방법이 있습니까? Python으로 무언가를 작성하려고 생각했지만 해당 컴퓨터(매우 느린 임베디드 장치)에서 Python을 시작하는 데 몇 초가 걸리며 이는 용납할 수 없습니다.

좀 더 명확하게 설명하자면 다음과 같습니다.

이 프로그램은 내 통제하에 있지 않으므로 프로그램이 수행하는 작업을 변경할 수 없습니다. 그렇지 않으면 프로그램에서 이러한 오류 메시지 출력을 중지하게 됩니다. 이 프로그램은 Cisco-Shell 모드에서 장치의 설정을 보거나 변경하는 데 사용됩니다. 일반적인 사용자 상호 작용은 다음과 같습니다.

linux-shell# command
% Error: some meaningless error
fake-cisco-shell# show status
Status report: status ok
% Error: some meaningless error
fake-cisco-shell# exit
linux-shell#

사용자가 키를 누를 때마다 입력하는 문자가 화면에 나타나므로 일반 bash 셸에서와 마찬가지로 입력한 내용을 볼 수 있습니다.

이제 다음과 같이 하면:

command | grep -v "%[^\n]*\n"

그러면 입력한 문자(및 입력 프롬프트)는 사용자가 Enter를 누르고 줄을 마친 후에만 표시됩니다. 왜냐하면 grep이 줄을 캐시하기 때문입니다. 따라서 다음과 같습니다("<" = 사용자의 입력, ">" 프로그램의 출력).

> fake-cisco-shell# 
< s
> s
< h
> h
< o
> o
< w
> w
< \n
> \n
> Result of the command\n
> fake-cisco-shell#

이제 다음과 같이 보입니다.

>(no output)
< s
< h
< o
< w
< \n
> fake-cisco-shell# show\n
> Result of the command\n

보시다시피, 프로그램이 문자를 보낼 때 각 문자를 개별적으로 출력하지 않고 대신 다음 \n을 기다린 다음 콘텐츠를 grep 전달합니다.

grep이 실제로 내가 원하는 것을 수행할 수 있는지 확신할 수 없으므로 다른 프로그램에 대한 제안에도 열려 있습니다.

답변1

grep한정된행을 일치시키거나 유지하거나 삭제하므로 원하는 결과를 얻지 못하면 일치하기 전에 전체 행을 읽어야 합니다.

command먼저 입력 문자가 하나씩 파이프에 에코되는지 확인해야 합니다 . 표준 C 프로그램(때때로 C stdio를 사용하는 다른 프로그램)은 stdout이 구현 정의 "대화형 장치"인 경우 기본적으로 라인 버퍼링을 사용하고, 그렇지 않으면 전체 버퍼링을 사용하며 파이프는 일반적으로 대화형으로 정의되지 않습니다. 당신 command은 이미 tty에서 이상하게 행동하고 있습니다. 그러나 command | dd bs=1.

command그래도 작동하지 않으면 Mark Plotnick이 제안한 간소화된 프로그램 과 같은 의사 tty(pty)를 구축하기 위한 프로그램이 필요합니다 .script

에코 파이프라인이 측면에서 작동하는 경우 command필요한 것은 전체 라인을 기다리지 않고 파이프라인의 오른쪽에 있는 것뿐입니다. 간단한 C 프로그램으로 이를 수행할 수 있습니다. 예를 들면 다음과 같습니다.

#include <stdio.h>
int main (void) {
  setvbuf (stdout, NULL, _IONBF, 0);
  int c;
  while( (c = getchar()) != EOF ){
    int sel = c != '%';
    for( ; c != '\n' && c != EOF; c = getchar() ) 
      if( sel ) putchar (c);
    if( sel ) putchar ('\n');
  }
}

또는 (IMLE 내장 장치는 그렇지 않은 경향이 있음 bash) 다음을 포함하는 스크립트를 시도하십시오.

IFS=$'\n'
while read -rn1 c; do y=true; [[ "$c" == "%" ]] && y=false;
  while ! [[ "$c" == "" ]]; do $y && printf "%c" "$c"; read -rn1 c || exit; done
  $y && printf "\n"; done

답변2

줄의 시작 부분에는 Perfect를 사용 ^하고 줄의 끝 부분에는 Perfect를 사용하세요 $. \n문자를 인식할 수 없습니다. 그리고 줄 끝은 절대 일치하지 않습니다(기본적으로).

그래서 당신은 그런 것을 사용해야합니다 grep -v "^%.*$".

답변3

sed버퍼링되지 않은 모드가 있으므로 다음도 작동합니다.

… | sed -u -r '/%[^\n]*\n/d'

관련 정보