2017-07-16 34 views
0

我想知道是否有辦法在bash中的文本文件的某一行之後刪除所有內容。所以說有一個10行的文本文件,我想刪除第4行後的每一行,所以只剩下前4行,我該如何去做?刪除bash中的某一行後的所有內容

+0

後輸入例如 – RomanPerekhrest

+0

你的意思是輸入的例子嗎?會有有很多行的文件,名爲file.txt說了,我只想修剪一定行之後的所有文本。 – John

+1

簡單的是'頭-4的oldfile> newfile',然後'MV newfile中oldfile'。這不是「到位」,但不知道什麼是必要的。 – cdarke

回答

1

您可以使用GNU sed

sed -i '5,$d' file.txt 

也就是說,5,$表示範圍線5,直到結束,d表示刪除。 只剩下前四行。 -i標誌告知sed就地編輯文件。

如果你只有BSD sed,則-i標誌需要備份的文件後綴:

sed -i.bak '5,$d' file.txt 

由於@ephemient指出,雖然這種解決方案很簡單, 這是低效的,因爲sed仍然會讀取輸入,直到文件的結尾,這是不必要的。

由於@agc指出,我的第一個建議的反向邏輯可能實際上更直觀。也就是說,不通過默認(-n標誌), 打印並明確地打印範圍1,4

sed -ni.bak 1,4p file.txt 

另一種簡單的替代方案中,假定第一4行也不會過長,所以它們容易地配合在存儲器中,並還假設第四線以換行符, 可以讀取前4行到存儲器中,然後覆蓋該文件結束時:

lines=$(head -n 4 file.txt) 
echo "$lines" > file.txt 
+0

注意,在* BSD(包括OS X),'sed的-i '5,$ d' file.txt'將使用''5,$ D''作爲備份後綴和'file.txt'作爲表達式,這不是你想要的。沒有簡單的便攜式方法來執行就地的'sed'而不創建備份文件。 – ephemient

+0

謝謝,這個回答我的問題。 – John

+0

@ephemient謝謝,修正 – janos

2

sed方法@janos是簡單的,但低效率的。它會讀取原始文件中的每一行,甚至可以忽略它(儘管可以使用4q修復),而-i實際上會創建一個新文件(它將重命名以替換原始文件)。還有一個煩人的地方,你需要將GNU sed使用sed -i '5,$d' file.txt,但使用BSD sed的sed -i '' '5,$d' file.txt以刪除現有文件而不是留下備份。

dd bs=1 count=0 if=/dev/null of=file.txt \ 
    seek=$(grep -b^file.txt | tail -n+5 | head -n1 | cut -d: -f1) 
  • grep -b^file.txt打印出的字節偏移上的每一行,例如:

    執行更少的I/O的另一種方法

    $ yes | grep -b^
    0:y 
    2:y 
    4:y 
    ... 
    
  • tail -n+5跳過前4行,輸出5 和後續行

  • head -n1只對下一行(例如,僅5 線)

    head讀取一行,它將退出。這導致tail退出,因爲它無處可輸。這導致grep出於同樣的原因。因此,file.txt的其餘部分不需要檢查。

  • cut -d: -f1只需要第一部分使用1個字節的塊大小:(字節偏移)

  • dd bs=1 count=0 if=/dev/null of=file.txt seek=N

    • 之前,設法阻止file.txt

    • N

      /dev/null複製0個大小爲1字節的塊到file.txt

    • 截斷file.txt這裏(因爲conv=notrunc未給出)

    總之,這消除了對5個和後續行從file.txt的所有數據。

    在Linux上有一個名爲fallocate的命令,它可以類似地擴展或截斷文件,但這不是可移植的。

UNIX文件系統支持有效地截斷文件,並且這些命令是可移植的。缺點是寫出更多的工作。

(此外,dd會向stderr打印一些不必要的統計信息,並且如果文件少於5行,將會退出並顯示錯誤,但在這種情況下,它將保留現有文件內容,因此行爲仍然存在如果需要,也可以解決。)

+1

比'seek = $更簡單的方法(grep的-b^file.txt的|尾-n + 5 | -n1頭|切-d:-f1)''是尋求= $(頭-n4 file.txt的| WC -c | TR -d'「) ' – janos

0

使用GNU awk(v 4.1.0+,參見here)。首先,我們創建一個測試文件(注意免責聲明):

$ seq 1 10 > file  # THIS WILL OVERWRITE FILE NAMED file WITH TEST DATA 

然後代碼和驗證(將修改名爲file原始文件):

$ awk -i inplace 'NR<=4' file 
$ cat file 
1 
2 
3 
4 

解釋:

$ awk -i inplace ' # edit is targetted to the original file (try without -i ...) 
NR<=4    # output first 4 records 
' file    # file 

你也可以在NR==5行退出,如果你將程序的輸出重定向到一個新文件(刪除#的行爲)會更快,是一樣的head -4 file > new_file

$ awk 'NR==5{exit}1' file # > new_file 

測試時,先不要忘了seq部分。

1

Janos' answerephemient's answer小的改進,和cdark's comment

  1. 更簡單,速度更快sed代碼:

    sed -i 4q file 
    
  2. 當過濾器UTIL不能直接編輯文件時,有 sponge

    head -4 file | sponge file 
    
  3. 最有效的Linux的可能是truncatecoreutils兄弟UTIL到fallocate,它提供了相同的最小I/O的ephemient的更復雜,但是更便攜dd爲基礎的答案):

    truncate -s `head -4 file | wc -c` file 
    
相關問題