`awk 'NF {p=1} p'` 如何從檔案的開頭和結尾刪除空白行?

`awk 'NF {p=1} p'` 如何從檔案的開頭和結尾刪除空白行?

在尋找一種從文件的開頭和結尾刪除空白行(使用tac)的方法時,我偶然發現了這個:

awk 'NF {p=1} p'

這是如何/為什麼有效的?

我理解NFtrue當有任何欄位時(如果該行不是空白行)。

答案1

這將從頭開始刪除空白行,但不是從最後開始一個文件的。[註:此答案是在編輯問題提到的tac]

其工作原理如下:

  • NF是在目前行找到的字段數。如果為零,則表示該行為空或空白的,即最多包含空格(假設欄位分隔符號保留其預設值,其中任意數量的連續空格都被視為分隔符號)。
  • { ... }如果規則區塊 ( ) 之外(且不與其關聯)的任何條件計算結果為 ,則列印目前行true。該標誌p最初未初始化,且計算結果為false,因此先驗不會列印任何內容。
  • 一旦找到非空白行(NF非零且計算結果為true),則輸入規則區塊{p=1}並將標誌p設為1。之後,p規則區塊的外部計算為true,並列印任何後續行(包括當前的第一個非空白行)。

注意由於該標誌p永遠不​​會重置,因此第一個非空白行之後的任何空白行都將列印而不進行過濾。如果您也想從末尾刪除空白行,則需要採用兩遍方法:

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

這將處理文件兩次(因此它被指定為操作數兩次)

  • 在第一遍中,FNR其中每個文件行計數器等於NR全域行計數器,我們識別第一個和最後一個非空行。
  • 在第二遍(FNR現在小於NR)中,我們只列印如此標識的第一行和最後一個非空白行之間(並包括)的行。

注意

如中所述史蒂芬·查澤拉斯的回答,兩遍方法僅適用於常規文件。如果您的輸入具有不同的性質,請參閱此處提出的解決方案的方法。

答案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 的回答例如,但為了完整起見,我將建議一種替代方法來刪除前導和尾隨空白行,而不必對文件進行兩次傳遞(這僅適用於常規文件,不適用於任意輸入)。

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

我們將空白行的列印延遲到我們隨後看到的下一個非空白行(前提是我們之前已經看到過至少一個非空白行)。

答案4

如果您不介意破壞要保留的空白行上的任何空格或製表符,這將從開頭和結尾刪除空白行:

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

它計算非空行之間出現的空行數,並在每個非空白行之前列印那麼多空行。

相關內容