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まず、入力文字が1つずつパイプにエコーされていることを確認する必要があります。標準 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

おすすめ記事