如何在Linux中讀取檔案中特定的一行?


在使用Linux shell時,讀取文字檔案通常是一個重要的操作。有時,我們可能只對讀取檔案中的特定一行感興趣。

我們將看看從檔案中獲取特定文字的不同方法。

實際問題

讓我們來看一個例子。

假設我們有一個名為“test.txt”的檔案:

$ nl test.txt
1 This is line 1, I don't have any interesting data.
2 This is line 2, I don't have any interesting data.
3 This is line 3, I don't have any interesting data.
4 This is line 4, I don't have any interesting data.
5 This is line 5, interesting data: Linux is awesome!
6 This is line 6, I don't have any interesting data.
7 This is line 7, I don't have any interesting data.

我們使用nl函式顯示帶有行號的文字檔案內容。

我們知道前四行包含一些有趣的資訊。因此,我們只想讀取第五行。

在Linux命令列中有很多方法可以做到這一點。在本指南中,我們將介紹四種不同的方法:

  • 使用Bash命令

  • 使用sed命令

  • 使用awk命令

  • 使用headtail命令

讓我們來看一些例子。

使用Bash命令

為了解決這個問題,我們需要編寫一個名為getLine的shell指令碼。

$ cat getLine.sh
#!/bin/bash
FILE="$1"
LINE_NO=$2
i=0
while read line; do
   i=$(( i + 1 )
   test $i = $LINE_NO && echo "$line";
done <"$FILE"

上面的shell指令碼接受兩個引數:檔名和目標行號。

基本上,它包含一個段落。我們首先將$i的值設定為零。然後我們檢查當前行是否與我們目標的行(第十行)匹配。如果是,我們將$i加1。否則,我們將列印當前行。

命令

$ ./getLine.sh test.txt 5

輸出

This is line 5, interesting data: Linux is awesome!

結果顯示我們的指令碼執行成功。

如果我們仔細閱讀文字,我們可能會改進它。

我們在迴圈中檢查字串中的每一個字元,即使我們已經找到並列印了我們想要的字元。實際上,我們可能在找到我們想要的內容之前處理了大量資料。但是,讓我們堅持這個例子!我們的示例輸入只有七行。然而在現實世界中,您的輸入可能包含數百萬行。

因此,如果我們能夠在找到正確的行後退出迴圈,那就太好了。所以,讓我們稍微修改一下指令碼:

$ cat getLine2.sh
#!/bin/bash
FILE="$1"
LINE_NO=$2
i=0
while read line; do
   i=$(( i + 1 ))
   case $i in $LINE_NO) echo "$line"; break;; esac done <"$FILE"

我們使用case語句在找到我們想要的行時停止迴圈。讓我們看看它是否有效:

命令

$ ./getLine2.sh test.txt 5

輸出

This is line 5, interesting data: Linux is awesome!

我們透過使用一些bash指令碼解決了這個問題。

使用sed命令

sed命令非常擅長解決這類問題。這裡有兩個簡潔的sed單行命令可以完成這項工作。

命令

$ sed '5!d' test.txt

輸出

This is line 5, interesting data: Linux is awesome!

命令

$ sed -n '5p' test.txt

輸出

This is line 5, interesting data: Linux is awesome!

要刪除目錄中除第五行(也是唯一一行)以外的所有行,請使用以下命令:5!d 要只顯示第五行(也是唯一一行),請使用以下命令:-n '5p'

這兩個單行指令碼按預期執行。但是,它們會逐行讀取整個輸入,這對於大型檔案來說花費的時間太長。

shell指令碼提供了一個“q”(退出)選項來退出進一步的執行。因此,我們可以使用“&&”運算子將這兩個命令組合成一行:

命令

$ sed '5!d;q' test.txt

輸出

This is line 5, interesting data: Linux is awesome!

命令

$ sed -n '5{p;q}' test.txt

輸出

This is line 5, interesting data: Linux is awesome!

我們沒有注意到兩個輸出之間的任何差異,因此讓我們使用sed -e's/^.*$//'命令刪除從每一行開頭到行尾的所有內容。

讓我們首先快速瀏覽一下沒有“q”命令的版本。

命令

$ sedsed -d '5!d' test.txt

輸出

PATT:This is line 1, I don't have any interesting data.$
HOLD:$
COMM:5 !d
PATT:This is line 2, I don't have any interesting data.$
...
This is line 5, interesting data: Linux is awesome!
PATT:This is line 6, I don't have any interesting data.$
HOLD:$
COMM:5 !d
PATT:This is line 7, I don't have any interesting data.$
HOLD:$
COMM:5 !d

然後我們可以看到sed命令已經從第一個字元處理到最後一個字元(第七個字元)。

我們現在將使用q測試sed命令。

命令

$ sedsed -d '5!d;q' test.txt

輸出

PATT:This is line 1, I don't have any interesting data.$
HOLD:$
COMM:5 !d
PATT:This is line 2, I don't have any interesting data.$
...
PATT:This is line 5, interesting data: Linux is awesome!$
HOLD:$
COMM:q
This is line 5, interesting data: Linux is awesome!

除錯輸出表明sed處理在第5行停止。

使用awk命令

另一個強大的文字處理工具是awk。您可以使用它用一行程式碼來解決問題:awk 'NR == 5' input.txt。

我們不想在列印第5行後繼續處理。

類似地,awk也有“quit”命令來退出當前處理。

命令

$ awk 'NR==5{ print; exit }' test.txt

輸出

This is line 5, interesting data: Linux is awesome!

因此,如輸出所示,我們已經解決了這個問題。

使用headtail命令

我們可以使用`tail`命令提取文字文件的最後部分。

我們還可以使用這兩個命令的組合來讀取特定行。

讓我們假設我們要讀取x行。思路是:

  • 我們首先使用head命令從輸入檔案中獲取第1行到第X行。

  • 然後我們將第一步的輸出透過管道傳遞到tail命令以檢索最後一個條目:head -n X input | tail -1

讓我們看看這個想法對我們的例子是否有效:

命令

$ head -n 5 test.txt | tail -1

輸出

I am line 5, interesting data: Linux is awesome!

我們得到了預期的結果,並且我們解決了這個問題。

結論

我們討論了在Linux中從輸入檔案讀取單行的不同方法。

我們討論瞭如何提高bash、awk和/或sed解決方案的效能。

更新於:2022年12月1日

15K+ 次瀏覽

啟動你的職業生涯

透過完成課程獲得認證

開始
廣告
© . All rights reserved.