Sed

如何從出現特定模式的行開始剪切文件?

  • December 11, 2021

我有大量文件需要縮小。我發現大多數(不是全部)文件都有一個結尾部分,可以在不失去資訊的情況下進行剪切:

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/那樣編寫文件的新副本edgawk -i inplaceperl

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呼叫次數。

引用自:https://unix.stackexchange.com/questions/569097