Sed
如何從出現特定模式的行開始剪切文件?
我有大量文件需要縮小。我發現大多數(不是全部)文件都有一個結尾部分,可以在不失去資訊的情況下進行剪切:
Data 1 Data 2 something_unimportant_here END DATA Rubbish 1 Rubbish 2
如何通過刪除包含“END DATA”的行以及所有後續行來編輯文件(因此全部結束),就地,僅更改那些包含該模式的文件,從而最大限度地減少對磁碟的寫訪問(很多很多文件和慢速磁碟)。
如果可能的話,我想在文件中添加一個新的最後一行(我自己的結束標記),以便文件的語法保持正確——同樣,僅在那些包含該模式的文件中。
我正在考慮使用
ed
,比如echo ',s/END DATA/ ???? '\\n'q'\\n'wq' | ed "$file"
但似乎無法管理???? 部分正確。
預期輸出:
Data 1 Data 2 NEW END
聽起來您正在尋找的命令序列是
/END DATA/,$d q .a NEW END . wq
或作為單線
printf '%s\n' '/END DATA/,$d' 'q' '.a' 'NEW END' '.' 'wq'
(您可以替換
wq
為,p
進行測試。)前任。給定
$ cat file Data 1 Data 2 something_unimportant_here END DATA Rubbish 1 Rubbish 2
然後
$ printf '%s\n' '/END DATA/,$d' 'q' '.a' 'NEW END' '.' 'wq' | ed -s file
給
$ cat file Data 1 Data 2 NEW END
您應該能夠通過在原地截斷文件來做到這一點,而不必像
sed -i
//perl -i
/那樣編寫文件的新副本ed
。gawk -i inplace
與perl
:find . -name '*.txt' -type f -exec perl -ne ' BEGIN{@ARGV=map{"+<$_"}@ARGV} # open files in read+write mode in the # while(<>) loop implied by -n if (/END DATA/) { seek ARGV,-length,1; # back to beginning of matching line print ARGV "NEW END\n"; truncate ARGV, tell ARGV; close ARGV; # skip to next file }' {} +
這將 I/O 最小化,
perl
因為一旦找到匹配項就停止讀取,並且NEW END\n
是它唯一寫入的內容。它還寫入到位,因此文件元數據(所有權、權限、acls、稀疏性……)被保留,硬連結不會被破壞。
-exec {} +
我們還可以最大限度地減少perl
呼叫次數。