簡體   English   中英

根據 header 和頁腳行拆分文件

[英]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

我需要找到headerfooter之間的每個部分並將其保存在另一個文件中。 例如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 的行,我將當前行( $0print到名為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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM