`awk 'NF {p=1} p'` ファイルの先頭と末尾から空白行を削除するには?

`awk 'NF {p=1} p'` ファイルの先頭と末尾から空白行を削除するには?

(を使用して)ファイルの先頭と末尾から空白行を削除する方法を探している間に、tac次のことがわかりました。

awk 'NF {p=1} p'

これはどのように/なぜ動作しますか?

フィールドがある場合(行が空の行でない場合)のみをNF理解してください。true

答え1

これにより、最初から空白行が削除されます。しかし最後からではありません。ファイルの。[注:この答えは質問を修正言及tac]

仕組みは次のとおりです。

  • NF現在行で見つかったフィールドの数。 0の場合、行が空かスペースつまり、最大スペースを含めます(フィールド区切り文字がデフォルト値のままであると仮定し、連続するスペースの数は区切り文字と見なされます)。
  • { ... }ルールブロックの外側(および関連付けられていない)の条件がと評価されると、現在の行が印刷されますtrue。このフラグはp最初は初期化されずに評価されるため、false事前に何も印刷されません。
  • 空でない行が見つかった場合(NFゼロではないと評価されているtrue)、ルールブロックを入力して{p=1}フラグpをに設定します1。その後、pルールブロックの外側が評価され、trueすべての後続の行(現在空でない最初の行を含む)が印刷されます。

気づくこのフラグはpリセットされないため、空でない最初の行以降の空白行はすべてフィルタリングせずに印刷されます。最後の空白行も削除するには、2段階のアプローチを実行する必要があります。

awk 'FNR==NR{if (NF) {if (!first) first=FNR; last=FNR} next}
     FNR>=first && FNR<=last' input.txt input.txt

その後、ファイルは2回処理されます(したがってオペランドとして2回指定されます)。

  • 各ファイルラインカウンタがグローバルラインカウンタFNRと同じ最初のパスでは、空でない最初の行と最後の行を識別します。NR
  • 2番目のパス(FNR今より小さいNR)は、識別された最初の行と空でない最後の行の間の行のみを印刷します。

気づく

で述べたようにStephen Chazerasの答え、2段階の方法は通常のファイルでのみ機能します。入力内容が性格が異なる場合は、ここで提案されているソリューションへのアプローチをご覧ください。

答え2

ファイルの先頭と末尾から空白行を削除するには、この手法を使用します。

awk 'NF {p=1} p' file | # remove blank lines at the file head
  tac |                 # reverse the lines
  awk 'NF {p=1} p' |    # remove blanks from the "new head"
  tac |                 # re-reverse the file
  sponge file           # from the `moreutils` package, to overwrite the file

答え3

コードの機能と入力の先頭の空行のみを削除する理由はすでに説明されています。@AdminBeeからの返信たとえば、完全性を確保するためにファイルを2回通過することなく、前後の空白行を削除する代替方法を提案します(この方法は、任意の入力ではなく通常のファイルでのみ機能します)。

awk '
       NF {print saved $0; saved = ""; started = 1; next}
  started {saved = saved $0 ORS}' < file

その後に表示される空白でない次の行が表示されるまで、空白行の印刷を遅らせます(以前に空でない行を1つ以上見たことがある場合)。

答え4

保持したい空白行から空白やタブを分離しても構わない場合は、開始と終了の空白行が削除されます。

awk 'NF{for(;c;--c)print "";print;x=1;next} x{++c}'

空でない行の間に現れる空の行数を計算し、空でない各行の前にその数の空行を印刷します。

関連情報