在尋找一種從文件的開頭和結尾刪除空白行(使用tac
)的方法時,我偶然發現了這個:
awk 'NF {p=1} p'
這是如何/為什麼有效的?
我理解NF
僅true
當有任何欄位時(如果該行不是空白行)。
答案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}'
它計算非空行之間出現的空行數,並在每個非空白行之前列印那麼多空行。