2017-08-13 69 views
0

Bash版本4.4.7。奇怪的結果,同時執行閱讀'頭'和'尾'Cat輸出'第一和最後一行'

tutorial,以獲得第一和文件的最後一行:

cat txt_file | (head -n1 && tail -n1) 

但是,對於大文件(我不知道有多大,這將工作,但與文件有關千行)該命令運行良好,但對於小的文件,例如:

11111111 
22222222 
33333333 
44444444 

命令的輸出大約是僅在第一行:

11111111 

其他命令,用awk,作品有兩個文件:

awk 'NR==1; END{print}' 
+2

對我來說,這似乎並不奇怪......除非輸入大於任何緩衝區大小,否則不太可能出現「head && tail」。 – donkopotamus

+0

@donkopotamus我不知道,你能解釋一下嗎?以及如何讓這個例子的頭部,尾部工作!謝謝! – duqu

+0

你能解釋一下它是如何工作的嗎?每個命令一次加載一個緩衝區,嘗試用該緩衝區終止,然後將剩餘的緩衝區交給下一個命令?通常緩衝區大小有多大?或者我怎麼能找到這個結果? – rubystallion

回答

3

你的「問題」此刻實際上並沒有提出一個問題,它只是一個觀察。然而,解釋你的觀察。考慮的輸出之間的差別:

$ seq 10 | (head -1 && tail -1) 
1 

$ seq 1000 | (head -1 && tail -1) 
1 
1000 

這到底是怎麼回事?我們的流水線工作如下:

  • 發送線(在這種情況下與數字,但其對你的cat例如沒有不同)到標準輸出;
  • 閱讀標準輸出,我們有:

    • 首先,head ......它將打印的第一行,然後結束;
    • 接下來,一個tail ...它將開始頭已運行並打印最後一行。

然而,在默認情況下,head不讀通過字符行,甚至字符文件中的行,直到它找到一個換行符,而不是它的讀取數據塊文件(緩衝讀) 。例如,該塊可能是2048個字節。

因此,我們的管道是真的:

  • 發送線(在這種情況下,與電話號碼,但它沒有什麼不同您cat例子)到標準輸出;
  • 閱讀標準輸出,我們有:

    • 首先,head ......它會讀取從標準輸入第一2KB,打印的第一行,然後結束;
    • 接下來,一個tail ...它會讀取其後的數據之後的第一個2K,因爲它從來沒有看到它

如果你的目標是隻產生了第一個命令的輸出(您cat)一次,那麼你可以使用tee,這樣或許還有:

$ seq 10 | tee >(tail -1) | head -2 

也要注意, Linux,你可以改變緩衝的第一個命令,如:

$ stdbuf -oL seq 10 | (head -1 && tail -1) 

但這不會工作,如果你的命令其流撥弄(見stdbuf)以下太

1

嘗試: SED解決方案:

sed -n '1p;$p' <(seq 1000) 

perl的解決方案:

seq 100 | perl -ne 'print if 1..1 or eof' 

只有尾巴bash的解決辦法:

seq 100 | { IFS= read -r line; echo "$line"; tail -1; }