【问题标题】:copy everything before the first blank line复制第一个空行之前的所有内容
【发布时间】:2016-03-19 20:08:11
【问题描述】:

我有一个文件,其中包含几个由空行分隔的文本块。例如:

block1
block1

block2

block3
block3

我需要一个使用 sed、awk 或 Perl 的解决方案来定位第一个空行并将前一个块重定向到另一个文件,依此类推,直到文件结束。

我在 sed 中有这个命令可以定位第一个块,而不是其余的:

sed -e '/./!Q'

有人可以帮我吗?

【问题讨论】:

  • 输出文件的文件名应该是什么。

标签: perl shell awk sed grep


【解决方案1】:

这可能对你有用(GNU csplit 和 sed):

csplit -qf uniqueFileName file '/^$/' '{*}' && sed -i '/^$/d' uniqueFileName*

或者如果你想使用默认值:

csplit -q file '/^$/' '{*}' && sed -i '/^$/d' xx*

用途:

tail -n+1 xx* # to check the results

【讨论】:

    【解决方案2】:

    考虑到block之间的几个空字符串

    awk '/./{if(!L)++C;print>"Out"C".txt"}{L=$0!~/^$/}' YourFile
    

    Sed 不允许不同的外部文件(实际上是未指定数量)作为输出

    【讨论】:

      【解决方案3】:

      在 Perl 中的另一种方法:

      #!/usr/bin/perl
      use strict;
      use warnings;
      
      # store all lines in $data
      my $data = do { local $/; <DATA> };
      
      my @blocks = split /\n\n/, $data;
      
      my $n = 0;
      write_to_file( 'file' . ++$n, $_ ) for @blocks;
      
      sub write_to_file {
          my $file = shift;
          my $data = shift;
      
          open my $fh, '>', $file or die $!;
          print $fh $data;
          close $fh;
      }
      
      __DATA__
      block1
      block1
      
      block2
      
      block3
      block3
      

      【讨论】:

        【解决方案4】:

        这是我在 Perl 中的解决方案:

        #!/usr/bin/perl
        use strict;
        use warnings;
        
        my $n     = 0;
        my $block = '';
        while (<DATA>) {    # line gets stored in $_
            if (/^\s*$/) {    # blank line
                write_to_file( 'file' . ++$n, $block );
                $block = '';
            } else {
                $block .= $_;
            }
        }
        
        # Write any remaining lines
        write_to_file( 'file' . ++$n, $block );
        
        sub write_to_file {
            my $file = shift;
            my $data = shift;
        
            open my $fh, '>', $file or die $!;
            print $fh $data;
            close $fh;
        }
        
        __DATA__
        block1
        block1
        
        block2
        
        block3
        block3
        

        输出:

        $ grep . file*
        file1:block1
        file1:block1
        file2:block2
        file3:block3
        file3:block3
        

        【讨论】:

          【解决方案5】:

          这是awk

          $ awk 'BEGIN{file="file"++cont}/^$/{file="file"++cont;next}{print>file}' infile
          

          结果

          $ cat file1 
          block1
          block1
          $ cat file2
          block2
          $ cat file3
          block3
          block3
          

          【讨论】:

            【解决方案6】:

            这是 Perl 中的解决方案

            open( my $fh, '<', '/tmp/a.txt' ) or die $!;
            
            {
                ## record delimiter
                local $/ = "\n\n";
                my $count = 1;
            
                while ( chomp( my $block = <$fh> ) ) {
                    open( my $ofh, '>', sprintf( '/tmp/file%d', $count++ ) ) or die $!;
                    print {$ofh} $block;
                    close($ofh);
                }
            
            }
            
            close($fh);
            

            【讨论】:

              【解决方案7】:

              试试这条线:

              awk -v RS=""  '{print > "file"++c".txt"}' input
              

              它将生成file1...n.txt

              【讨论】:

              • 这个选项看起来更紧凑。
              • 这样更好
              猜你喜欢
              • 1970-01-01
              • 2021-10-15
              • 1970-01-01
              • 1970-01-01
              • 2023-03-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多