[英]Split file into several files based on condition and also number of lines approximately
[英]split the file based on header and footer lines
我有一個結構如下的文本文件:
[timestamp1] header with space
[timestamp2] data1
[timestamp3] data2
[timestamp4] data3
[timestamp5] ..
[timestamp6] footer with space
[timestamp7] junk
[timestamp8] header with space
[timestamp9] data4
[timestamp10] data5
[timestamp11] ...
[timestamp12] footer with space
[timestamp13] junk
[timestamp14] header with space
[timestamp15] data6
[timestamp16] data7
[timestamp17] data8
[timestamp18] ..
[timestamp19] footer with space
我需要找到header
和footer
之間的每個部分並將其保存在另一個文件中。 例如file1應該包含(帶或不帶時間戳;無關緊要):
data1
data2
data3
..
下一個包應該保存為file2等等。 這似乎是一個常規過程,但我還沒有找到解決方案。
我有這個sed命令可以找到第一個數據包。
sed -n "/header/,/footer/{p;/footer/q}" file
但我不知道如何在接下來的比賽中重復這一點。 也許我應該在將第一個匹配項復制到另一個文件后刪除它並重復相同的命令
我將按照以下方式利用 GNU AWK
完成此任務,讓file.txt
內容為
[timestamp1] header with space
[timestamp2] data1
[timestamp3] data2
[timestamp4] data3
[timestamp5] ..
[timestamp6] footer with space
[timestamp7] junk
[timestamp8] header with space
[timestamp9] data4
[timestamp10] data5
[timestamp11] ...
[timestamp12] footer with space
[timestamp13] junk
[timestamp14] header with space
[timestamp15] data6
[timestamp16] data7
[timestamp17] data8
[timestamp18] ..
[timestamp19] footer with space
然后
awk '/header/{c+=1;p=1;next}/footer/{close("file" c);p=0}p{print $0 > ("file" c)}' file.txt
生成包含內容的file1
[timestamp1] header with space
[timestamp2] data1
[timestamp3] data2
[timestamp4] data3
[timestamp5] ..
和file2
內容
[timestamp8] header with space
[timestamp9] data4
[timestamp10] data5
[timestamp11] ...
和file3
的內容
[timestamp15] data6
[timestamp16] data7
[timestamp17] data8
[timestamp18] ..
說明:我的代碼有 3 個模式動作對,對於包含header
的行,我將計數器c
增加 1,並將標志p
設置為 1,並將 go 設置到next
行,因此不執行其他操作,對於包含footer
的行,我關閉名為file
的文件,然后是當前計數器編號並將標志p
設置為 0。對於p
設置為 true 的行,我將當前行( $0
) print
到名為file
的文件,后跟當前計數器編號。 如果需要,調整/header/
和/footer/
以僅在 header 行和頁腳行上保持不變。
(在 GNU Awk 5.0.1 中測試)
使用任何 awk:
$ awk '/footer/{f=0} f{print > out} /header/{close(out); out="file" (++c); f=1}' file
$ head file?*
==> file1 <==
[timestamp2] data1
[timestamp3] data2
[timestamp4] data3
[timestamp5] ..
==> file2 <==
[timestamp9] data4
[timestamp10] data5
[timestamp11] ...
==> file3 <==
[timestamp15] data6
[timestamp16] data7
[timestamp17] data8
[timestamp18] ..
一種非常天真的方法,編碼速度很快,可以改進,但似乎在 awk 中有效:
BEGIN {
i = 0
}
{
if ($0 == "header") {
write = 1
} else if ($0 == "footer") {
write = 0
i = i + 1
} else {
if (write == 1) {
print $0 > "file"i
}
}
}
這可能對你有用(GNU csplit 和 sed):
csplit -qf file -b '%d' --supp file '/header/' '{*}' && sed -i '/footer/,$d' file? && rm file0
在header
上使用 csplit 將file
拆分為多個filen
文件,抑制匹配行。
使用 sed 刪除footer
和任何后續行。
刪除不需要的file0
文件。
選擇:
sed -En '/header/{x;s/.*/echo $((0&+1))/e;x};/header/,/footer/!b;//b;G;s/(.*)\n/echo "\1" >>file/e' file
基於THIS REGEX ,這是一個 ruby:
ruby -e 'cnt=1
$<.read.scan(/^.*\bheader\b.*\s+([\s\S]*?)(?=^.*\bfooter\b)/){
|b| File.write("File_#{cnt}.txt", b[0])
cnt+=1
}' file
生產:
$ head File_*
==> File_1.txt <==
[timestamp2] data1
[timestamp3] data2
[timestamp4] data3
[timestamp5] ..
==> File_2.txt <==
[timestamp9] data4
[timestamp10] data5
[timestamp11] ...
==> File_3.txt <==
[timestamp15] data6
[timestamp16] data7
[timestamp17] data8
[timestamp18] ..
如果要刪除時間戳:
ruby -e 'cnt=1
$<.read.scan(/^.*\bheader\b.*\s+([\s\S]*?)(?=^.*\bfooter\b)/){ |b|
File.write("File_#{cnt}.txt", b[0].gsub(/^\[[^\]]+\]\s+/,""))
cnt+=1
}' file
$ head File_*
==> File_1.txt <==
data1
data2
data3
..
==> File_2.txt <==
data4
data5
...
==> File_3.txt <==
data6
data7
data8
..
注意:如果您想要包含 header 和/或頁腳,只需移動捕獲組以包含您想要的內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.