通过分隔符提取文件的一部分

时间:2012-12-13 09:03:39

标签: perl shell

我有一个文件格式如下:

Preamble

---------------------
Section 1
...
---------------------

---------------------
Section 2
...
---------------------

---------------------
Section 3
...
---------------------

Afterwords

我想通过分隔符提取每个部分,以便我得到一个结果:

file0:

Section 1
...

文件1:

Section 2
...

file2的:

Section 3
...

...

有一种简单的方法吗?感谢。

4 个答案:

答案 0 :(得分:2)

[更新]使用chomp和$_会使这更短。

这应该这样做:

如果您的输入记录分隔符是21 -的序列,perl -ne可以轻松实现:

perl -ne 'BEGIN{ $/=("-"x21)."\n"; $i=0; } 
  do { open F, ">file".($i++); 
       chomp;
       print F; 
       close F; 
  } if /^Section/' yourfile.txt

应该有效,并创建文件file0 .. fileN

解释

更容易解释为独立的Perl脚本吗?

$/=("-"x21)."\n"; # Set the input-record-separator to "-" x 21 times
my $i = 0;        # output file number

open IN, "<yourfile.txt" or die "$!";

while (<IN>) {  # Each "record" will be available as $_ 
  do { open F, ">file".($i++); 
       chomp;     # remove the trailing "---..."
       print F;   # write the record to the file
       close F;   #
  } if /^Section/  # do all this only it this is a Section
}

Perl的awk血统在这里很有用,所以让我们为比较显示awk版本:

awk 'BEGIN{RS="\n-+\n";i=0} 
  /Section/ {chomp; print > "file_"(i++)".txt" 
}' yourfile.txt

perl版本相比,它实际上更短。 Perl中的$/RS中的awk变量。 Awk在这里占了上风:RS可能是正则表达式!

答案 1 :(得分:1)

你也可以使用shell:

#!/bin/bash

i=0
while read line ; do

 #If the line contain "Section " followed by a 
 #digit the next lines have to be printed
 echo "$line"|egrep -q "Section [0-9]+"
 if [ $? -eq 0 ] ; then
  toprint=true
  i=$(($i + 1))
  touch file$i
 fi

 #If the line contain "--------------------"  
 #the next lines doesn't have to be printed
 echo "$line"|egrep -q "[-]{20}"
 if [ $? -eq 0 ] ; then
  toprint=false
 fi

 #Print the line if needed
 if $toprint ; then
  echo $line >> file$i
 fi

done < sections.txt

答案 2 :(得分:1)

以下是您要找的内容:

awk '/^-{21}$/ { f++; next } f%2!=0 { print > "file" (f-1)/2 ".txt" }' file

结果:

file0.txt的内容:

Section 1
...

file1.txt的内容:

Section 2
...

file2.txt的内容:

Section 3
...

正如您所看到的,上述文件名为“零”索引。如果您希望将文件名“one”编入索引,只需将(f-1)/2更改为(f+1)/2即可。 HTH。

答案 3 :(得分:0)

根据您的文件格式,这里有一个选项:

use strict;
use warnings;

my $fh;
my $sep = '-' x 21;

while (<>) {
    if (/^Section\s+(\d+)/) {
        open $fh, '>', 'file' . ( $1 - 1 ) . '.txt' or die $!;
    }

    print $fh $_ if defined $fh and !/^$sep/;
}

在您的数据上,使用file0.txt .. file2.txt创建file0.txt,其中包含:

Section 1
...