如何使用sed基于标题(特定格式)信息分割数据

时间:2015-12-31 11:22:45

标签: regex sed

我需要根据标题信息拆分输入文件来打印数据。 我的输入文件看起来像

1S62DI          00002961143
BITS 
KOOLVISFILET 
KOKOSMELK 
PAPRIKA 
1S62DI          00002961168
BLEEKMIDDEL
SNIJBLOEMEN
ROOIBOSTHEE 
1S62DI          000029611234
SNIJBLOEMEN 
MOZZARELLA 
2SCHENKSTROOP 
ISVUILZAKKEN 
1S62DI          00002961253
BLEEKMIDDEL 
IJBLOEMEN 
PRIKAMIX 
IT  GRANEN 
ROOIBOSTHEE 

考虑 1S62DI 作为我的标题,我必须提取数据直到下一次出现 1S62DI 并附加我的标题行的子字符串。最终输出应该像

BITS  2961143
KOOLVISFILET 2961143
KOKOSMELK 2961143
PAPRIKA 2961143
BLEEKMIDDEL 2961168
SNIJBLOEMEN 2961168
ROOIBOSTHEE 2961168
SNIJBLOEMEN 29611234
MOZZARELLA 29611234
2SCHENKSTROOP 29611234
ISVUILZAKKEN 29611234
BLEEKMIDDEL 2961253
IJBLOEMEN 2961253
PRIKAMIX 2961253
IT  GRANEN 2961253
ROOIBOSTHEE 2961253

我试过

sed  '/^1S62DI/,/^1S62DI/{/^1S62DI/d; /^1S62DI/d; p;}' file_name

只是提取数据,但没有得到正确的结果。

编辑1: 输入文件是基于位置的文件。如果列有数据,它将打印,否则它不会打印任何内容。所以完整的例子如下:

1S62DI          00002961143
BITS 
KOOLVISFILET 
KOKOSMELK 
PAPRIKA 
1S62DI          00002962158
ROOIBOSTHEE                                 0000000800000007120  
ITABROODJES                                 0000000610000004209  0000028
CHENKSTROOP            [2.19]               0000000210000001869  
UISVUILZAKKEN                               0000001080000012852  
1S62DI          00002964138
BLEEKMIDDEL                                 0000001890000006615  0000035
SNIJBLOEMEN            [0.35]               0000000980000021462  0000219
PAPRIKAMIX                                  0000000030000000387  
MUESLIREPEN                                 0000000050000000495  0000099
1S62DI          00002965128
ROOMYOGHURT            [0.25]               0000001260000003150  0000025
BLEEKMIDDEL                                 0000000390000001365  0000035
NIJBLOEMEN             [2.19]               0000000530000011607  

编辑2: 更新了所需的输出,提取后,我需要将每个标题数据的最后7位附加到每一行。

BITS 2961143 
KOOLVISFILET 2961143
KOKOSMELK 2961143
PAPRIKA 2961143
ROOIBOSTHEE                                 0000000800000007120  2962158
ITABROODJES                                 0000000610000004209  0000028 2962158
CHENKSTROOP            [2.19]               0000000210000001869  2962158
UISVUILZAKKEN                               0000001080000012852  2962158
BLEEKMIDDEL                                 0000001890000006615  0000035 2964138
SNIJBLOEMEN            [0.35]               0000000980000021462  0000219 2964138
PAPRIKAMIX                                  0000000030000000387  2964138
MUESLIREPEN                                 0000000050000000495  0000099 2964138
ROOMYOGHURT            [0.25]               0000001260000003150  0000025 2965128
BLEEKMIDDEL                                 0000000390000001365  0000035 2965128
NIJBLOEMEN             [2.19]               0000000530000011607  2965128

3 个答案:

答案 0 :(得分:3)

对于多行内容,最好使用awk。例如:

$ awk 'BEGIN{FS=OFS="\t"}NF==2 {code=$2; next} {print $1, code}' a
BITS    00002961143
KOOLVISFILET    00002961143
KOKOSMELK   00002961143
PAPRIKA     00002961143
BLEEKMIDDEL 00002961168
SNIJBLOEMEN 00002961168
ROOIBOSTHEE     00002961168
SNIJBLOEMEN     000029611234
MOZZARELLA  000029611234
2SCHENKSTROOP   000029611234
ISVUILZAKKEN    000029611234
BLEEKMIDDEL     00002961253
IJBLOEMEN   00002961253
PRIKAMIX    00002961253
IT  GRANEN  00002961253
ROOIBOSTHEE     00002961253

这假设您的数据是以制表符分隔的。只要有两列,它就会将第二个值存储为代码。然后,它继续打印附加存储代码的单列记录。

如果您要删除前导0,只需说出+0,以便awk将字符串转换为整数:

$ awk 'BEGIN{FS=OFS="\t"}NF==2 {code=$2+0; next} {print $1, code}' a
BITS    2961143
...

但是,由于行可能包含多个列,因此请在评论中使用glenn jackmans的建议,并获取以1S62DI开头的那些行的代码:

awk -v header="1S62DI" '$1==header {value=$2+0; next}; {print $0, value}' file

答案 1 :(得分:2)

这是sed程序。我虽然使用awk。

sed -n '/^1S62DI[[:blank:]]\+0*/ {s///; h; n}; /^1S62DI/! {G; s/\n/ /; p}' file

评论(因为所有中等复杂的sed程序都需要)

sed -n '
    /^1S62DI[[:blank:]]\+0*/ {  # lines matching the header
        s///                    # remove the header word, spaces and leading zeros
        h                       # save remaining text in hold space
        n                       # next line
    }
    /^1S62DI/! {                # lines NOT matching the header
        G                       # append a newline and the hold space
        s/\n/ /                 # translate newline to space
        p                       # and print
    }
' file

答案 2 :(得分:0)

这可能适合你(GNU sed):

sed 's/^1S62DI[^1-9]*//;Ta;h;d;:a;G;s/\n/ /' file

从标题行中删除不需要的字符串,并将余数保存在保留空间(HS)中,然后删除该行。如果它不是标题行,即替换失败,则将HS附加到模式空间(PS)(这引入了将字符串与PS和HS分隔开的换行符),并用空格和打印替换此换行符。