web-dev-qa-db-ja.com

それ以外の場合、Awk NR:エントリがないテーブルのセクションヘッダーを削除する方法

日々変化するデータの表をまとめようとしています。エントリが30より大きい行のみを表示するように、テーブルをすでに要約しました。

ただし、元のテーブルに30を超えるエントリがない日もあります。それが起こったとき、私は要約で空であるセクション全体を必要としません。次に、それらのセクションのヘッダー全体を削除するにはどうすればよいですか?

理想的には、5つのセクションすべてにエントリがない場合は、行を印刷しないでください(または、「なし:30を超えるエントリはありません」という文字列だけを作成しようとしていた)。

5つのセクションを持つ要約テーブルの例summarised_output.txt:

=========================================================================================================
Month: Jun      

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================
Month: Jun     

Counter Name                                06/05 14:00     06/05 13:00     06/05 12:00     06/05 11:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================
Month: Jun      

Counter Name                                06/05 10:00     06/05 09:00     06/05 08:00     06/05 07:00
=========================================================================================================


=========================================================================================================
Month: Jun    

Counter Name                                06/05 06:00     06/05 05:00     06/05 04:00     06/05 03:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================
Month: Jun      

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================

ご覧のとおり、original_output.txtファイルに30を超えるエントリがないため、3番目のセクションは空です。ただし、ヘッダーはまだそこにあります。

私の要約コード(動作):

awk '$1=="Month:"||$1==""||$1=="Counter"||(index($1, "=")!=0)||$3>=30|| $4>=30 || $5>=30||$6>=30' original_output.txt>>summarised_output.txt

ヘッダーを削除しようとしました(機能しません):

touch summarised_output_temp.txt
awk '{if ($1=="Month:"||$1==""||$1=="Counter"||(index($1, "=")!=0)||$3>=30|| $4>=30 || $5>=30||$6>=30) print $0}' original_output.txt >> summarised_output_temp.txt
if (((wc -l < summarised_output_temp.txt)==42))
then
echo "None: there is no entry larger than 30" >> summarised_output.txt
else
cat output_7_temp.txt>>summarised_output.txt
fi

試行に対して受け取ったエラー:

line 3: ((: (wc -l output_7_temp.txt | awk {print $1})==42: syntax error: invalid arithmetic operator (error token is ".txt | awk {print $1})==42")
4
tthhss

GNU awkがあれば、次のスクリプトを実行できます。

awk -v RS='={105}[^=]*={105}' 'NF{print oRT,$0} {oRT=RT}' file

テーブルヘッダーは、複数行のレコード区切り文字RSとして設定されます。これは、105 =文字の2倍で構成され、その間に何かがあります。

変数RTは、各レコードのレコードセパレーターをキャッチしており、変数oRTに格納され、印刷する要素がいくつかある場合は次のレコードに出力されます(NFでキャッチされます)。

1
oliv

を含む実行可能スクリプトtest.awkを作成します

awk '
  # { print "read " $0 }
  /^SYS/ {
    if (H) {
      if (F) {print F} else { F="\r\n\r\n"}
      print H; H=""}
    print
    next
  }
  /^./ {
    H=$0
    for (i=1; i<5; i++) {
      getline
      H = H "\r\n" $0
    }
    next
  }
' $@

実行します

test.awk original_output.txt

「/ ^ SYS/{」は、データ行を認識するものに置き換えることができます。

1
Gerard H. Pille

この問題は、これらの方針に沿ってPerlで取り組むことができます。

コード

Perl -F'/^=+$/m' -lan -0777e '
   my($dashes) = /^(=+)$/m;
   shift @F; pop @F;
   while ( @F > 1 ) {
      my($h, $s) = splice @F, 0, 2;
      next if $s =~ /^(?:\h*\n)+$/;
      print join $dashes, q(), $h, $s, !@F ? q() : ();
   }
' input.txt

出力

=========================================================================================================
Month: Jun

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45



=========================================================================================================
Month: Jun

Counter Name                                06/05 14:00     06/05 13:00     06/05 12:00     06/05 11:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45



=========================================================================================================
Month: Jun

Counter Name                                06/05 06:00     06/05 05:00     06/05 04:00     06/05 03:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45



=========================================================================================================
Month: Jun

Counter Name                                06/04 18:00     06/04 17:00     06/04 16:00     06/04 15:00
=========================================================================================================
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45
SYS.SYS.SYS.SYS.SYS.SYS.                  : 45              45              45              45


=========================================================================================================

説明

  • 入力を一度に丸呑みする:-0777オプションをPerlそれを可能にします。
  • このファイル全体(現在は1つの長い文字列として扱われています)をダッシュ​​に沿って分割します:/ ^ = + $/mは、指定された行が何も含まない場合は常に等しいことを意味します上のファイル。
  • -aオプションは、Perlが分割された部分を配列@ F
  • -Perlのnオプションは、次のレコードを読み取る直前に自動印刷を無効にし、awk-入力から読み取られたレコードのループのようなもの。
  • まず、入力からの破線を保存します。
  • 分割操作では最初と最後の要素が空になるため、メインタスクを実行する前に@ F配列からそれらを削除することに注意してください。
  • @ F配列から一度に2つの要素(splice)を消費するwhileループを設定します。最初はヘッダーであり、 2番目のセクション。配列に少なくとも2つの要素が残っている限り、ループは継続します。
  • 重要な点は、ヘッダー/セクションデュオの処理をスキップするかスキップしないかを決定することです。そして、セクションが空の行だけで構成されている場合、または水平方向の空白のみで構成されている行(\ h)で構成されている場合に決定されます。その正規表現は/ ^(?:\ h *\n)+ $ /です
  • セクションが空でない場合は、ヘッダー/セクションデュオをダッシュ​​でつなぎ合わせるタスクが残ります。最後のヘッダー/セクションが一緒になるときに、四捨五入するためにダッシュを追加する必要があることに注意してください。
1
Rakesh Sharma

Olivの答えと同様に、おそらくもう少し簡単です。

gawk -v RS='=+\n' '
    NR % 2 == 0 {header = $0; next}
    /[^[:space:]]/ {printf "%s", RT header RT $0}
    END {print RT}
' output.txt 

=sの行をレコード区切り文字として使用します。その場合、ヘッダーはすべての偶数番号のレコードになります。また、空白以外の文字が含まれている場合、「コンテンツ」は空ではありません。

RTはa GNU awk固有の変数で、「レコード区切り文字であるRSで示されるテキストと一致する入力テキスト。レコードが読み取られるたびに設定されます。」を含みます。

1
glenn jackman