Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 如何精确匹配两个空行_Regex_Perl_Parsing - Fatal编程技术网

Regex 如何精确匹配两个空行

Regex 如何精确匹配两个空行,regex,perl,parsing,Regex,Perl,Parsing,我有一个关于正则表达式的问题。我有一个文件,我需要以这样一种方式解析它,我可以区分其中一些特定的文本块。这些文本块由两个空行分隔。有些文本块由3或1个空行分隔,但我需要2个。所以我有一段代码,这是\s*$^\s*$/正则表达式,我认为应该匹配,但它不匹配。 怎么了 $filename="yu"; open($in,$filename); open(OUT,">>out.text"); while($str=<$in>) { unless($str = /^\s*$^\s*

我有一个关于正则表达式的问题。我有一个文件,我需要以这样一种方式解析它,我可以区分其中一些特定的文本块。这些文本块由两个空行分隔。有些文本块由3或1个空行分隔,但我需要2个。所以我有一段代码,这是\s*$^\s*$/正则表达式,我认为应该匹配,但它不匹配。 怎么了

$filename="yu";
open($in,$filename);
open(OUT,">>out.text");
while($str=<$in>)
{
unless($str = /^\s*$^\s*$/){
print "yes";
print OUT $str;
}
}
close($in);
close(OUT);
干杯,
Yuliya

默认情况下,Perl一次读取一行文件,因此不会看到多行新行。以下代码选择以双新行结尾的文本

    local $/ = "\n\n" ;

    while (<> ) {

      print "-- found $_" ;
    }

默认情况下,Perl一次读取一行文件,因此您不会看到多个新行。以下代码选择以双新行结尾的文本

    local $/ = "\n\n" ;

    while (<> ) {

      print "-- found $_" ;
    }
反对赞成新答案

justintime的答案是告诉perl您想调用一行的结尾\n\n,这很聪明,而且会很好地工作。一个例外是,这必须完全匹配。根据您使用的正则表达式,它使空行上似乎有空格,在这种情况下,这将不起作用。此外,他的方法甚至会在2个以上的换行符上分裂,这在OP中是不允许的

为了完整性,要按照您要求的方式执行,如果文件不太大,无法使用所有内存,则需要将整个文件拼凑成一个变量,在大多数情况下,这可能很好

然后,我可能会说使用split函数将文本块分割成一组块。然后,您的代码将类似于:

#!/usr/bin/perl

use strict;
use warnings;

my $file = 'yu';
my $text;

open(my $fh, '<', $file);
{
  local $/; enables slurp mode inside this block
  $text = <$fh>;
}
close($fh);

my @blocks = split( 
  /
  (?<!\n)\n #check to make sure there isn't another \n behind this one
  \s*\n #first whitespace only line
  \s*\n #second "
  (?!\n) #check to make sure there isn't another \n after this one
  /x, # x flag allows comments and whitespace in regex
  $text
);  
请注意,由于当$out到达foreach块的末尾时,使用my按词汇打开$out,因此$out变量失效,即超出范围。当词法文件句柄发生这种情况时,该文件将自动关闭。你也可以用justintime的方法做类似的事情:

local $/ = "\n\n" ;

my $file_num = 1;
while (<>) {
  open(my $out, '>', $file_num++ . ".txt");
  print $out $block;
}
反对赞成新答案

justintime的答案是告诉perl您想调用一行的结尾\n\n,这很聪明,而且会很好地工作。一个例外是,这必须完全匹配。根据您使用的正则表达式,它使空行上似乎有空格,在这种情况下,这将不起作用。此外,他的方法甚至会在2个以上的换行符上分裂,这在OP中是不允许的

为了完整性,要按照您要求的方式执行,如果文件不太大,无法使用所有内存,则需要将整个文件拼凑成一个变量,在大多数情况下,这可能很好

然后,我可能会说使用split函数将文本块分割成一组块。然后,您的代码将类似于:

#!/usr/bin/perl

use strict;
use warnings;

my $file = 'yu';
my $text;

open(my $fh, '<', $file);
{
  local $/; enables slurp mode inside this block
  $text = <$fh>;
}
close($fh);

my @blocks = split( 
  /
  (?<!\n)\n #check to make sure there isn't another \n behind this one
  \s*\n #first whitespace only line
  \s*\n #second "
  (?!\n) #check to make sure there isn't another \n after this one
  /x, # x flag allows comments and whitespace in regex
  $text
);  
请注意,由于当$out到达foreach块的末尾时,使用my按词汇打开$out,因此$out变量失效,即超出范围。当词法文件句柄发生这种情况时,该文件将自动关闭。你也可以用justintime的方法做类似的事情:

local $/ = "\n\n" ;

my $file_num = 1;
while (<>) {
  open(my $out, '>', $file_num++ . ".txt");
  print $out $block;
}
新答案

在排除了2条以上的空行之后,在这里睡个好觉是一个更好的方法,甚至不需要发出咕噜声

#!/usr/bin/perl

use strict;
use warnings;    

my $file = 'yu';
my @blocks; #each element will be an arrayref, one per block
            #that referenced array will hold lines in that block

open(my $fh, '<', $file);

my $empty = 0;
my $block_num = 0;
while (my $line = <$fh>) {
  chomp($line);
  if ($line =~ /^\s*$/) {
    $empty++;
  } elsif ($empty == 2) { #not blank and exactly 2 previous blanks
    $block_num++; # move on to next block
    $empty = 0;
  } else {
    $empty = 0;
  }

  push @{ $blocks[$block_num] }, $line;
}

#write out each block to a new file
my $file_num = 1;
foreach my $block (@blocks) {
  open(my $out, '>', $file_num++ . ".txt");
  print $out join("\n", @$block);
}
事实上,您不必稍后存储和写入,只需在运行时对每个块写入一个文件即可:

#!/usr/bin/perl

use strict;
use warnings;

my $file = 'yu';

open(my $fh, '<', $file);

my $empty = 0;
my $block_num = 1;
open(OUT, '>', $block_num . '.txt');
while (my $line = <$fh>) {
  chomp($line);
  if ($line =~ /^\s*$/) {
    $empty++;
  } elsif ($empty == 2) { #not blank and exactly 2 previous blanks
    close(OUT); #just learned this line isn't necessary, perldoc -f close
    open(OUT, '>', ++$block_num . '.txt');
    $empty = 0;
  } else {
    $empty = 0;
  }

  print OUT "$line\n";
}

close(OUT);
新答案

在排除了2条以上的空行之后,在这里睡个好觉是一个更好的方法,甚至不需要发出咕噜声

#!/usr/bin/perl

use strict;
use warnings;    

my $file = 'yu';
my @blocks; #each element will be an arrayref, one per block
            #that referenced array will hold lines in that block

open(my $fh, '<', $file);

my $empty = 0;
my $block_num = 0;
while (my $line = <$fh>) {
  chomp($line);
  if ($line =~ /^\s*$/) {
    $empty++;
  } elsif ($empty == 2) { #not blank and exactly 2 previous blanks
    $block_num++; # move on to next block
    $empty = 0;
  } else {
    $empty = 0;
  }

  push @{ $blocks[$block_num] }, $line;
}

#write out each block to a new file
my $file_num = 1;
foreach my $block (@blocks) {
  open(my $out, '>', $file_num++ . ".txt");
  print $out join("\n", @$block);
}
事实上,您不必稍后存储和写入,只需在运行时对每个块写入一个文件即可:

#!/usr/bin/perl

use strict;
use warnings;

my $file = 'yu';

open(my $fh, '<', $file);

my $empty = 0;
my $block_num = 1;
open(OUT, '>', $block_num . '.txt');
while (my $line = <$fh>) {
  chomp($line);
  if ($line =~ /^\s*$/) {
    $empty++;
  } elsif ($empty == 2) { #not blank and exactly 2 previous blanks
    close(OUT); #just learned this line isn't necessary, perldoc -f close
    open(OUT, '>', ++$block_num . '.txt');
    $empty = 0;
  } else {
    $empty = 0;
  }

  print OUT "$line\n";
}

close(OUT);

由两条空线分隔的块是什么意思?如何描述一个有效的块,您能举个例子吗?^和$匹配字符串的开头和结尾,而不是行。要匹配行的开始/结束,您需要添加/m regex修饰符:$x=~/^line1$^line2$/m结果是比我最初认为的更棘手的问题。欢迎来到SO。用两条空线分隔的街区是什么意思?如何描述一个有效的块,您能举个例子吗?^和$匹配字符串的开头和结尾,而不是行。要匹配行的开始/结束,您需要添加/m regex修饰符:$x=~/^line1$^line2$/m结果是比我最初认为的更棘手的问题。欢迎来到SO。在这个例子中,整个文件是一堆有效的块。结束一个相关的问题。如何使用perl将每个文本块写入另一个文本文件?我的意思是,如果我有几个区块,我想将它们写入另一个文件,可能会有50个这样的区块,我不能再同意这种方法了。这将无法正确处理>2个空行,也无法处理空行但仍包含空格的行,正如OP的正则表达式所指出的那样。这是一个聪明的想法。在这个例子中,整个文件是一堆有效的块。结束一个相关的问题。我如何用perl将每个文本块写入另一个文本文件?我的意思是,如果我有几个区块,我想将它们写入另一个文件,可能会有50个这样的区块,我不能再同意这种方法了。这将无法正确处理2条以上的空行
并且不会处理空行但仍包含空格的行,正如OP的正则表达式所指出的那样。这是一个聪明的想法。@gangabass,你当然是对的,我将把它转换为正确的形式,它首先本地化$。在我匆忙发帖的过程中,我忘了你必须在标量上下文中这样做,如果我改为在列表上下文中调用,这会起作用,但随后必须再次加入和拆分。更正。我也放弃了让OP的正则表达式工作,取而代之的是我的正则表达式。所以我在排除三个空行时遇到了问题。有谁能弄明白为什么会这样。此外,我认为为了简化,可能有必要使用s/^\s*$//。我将在这里展示该方法,甚至展示它的一些混乱和陷阱。我添加了一种新方法,它似乎工作得更高效、更有效、更可靠understandably@gangabass,您是对的,当然,我会将它切换到正确的格式,首先本地化$/的格式。在我匆忙发帖的过程中,我忘了你必须在标量上下文中这样做,如果我改为在列表上下文中调用,这会起作用,但随后必须再次加入和拆分。更正。我也放弃了让OP的正则表达式工作,取而代之的是我的正则表达式。所以我在排除三个空行时遇到了问题。有谁能弄明白为什么会这样。此外,我认为为了简化,可能有必要使用s/^\s*$//。我将在这里展示该方法,甚至展示它的一些混乱和陷阱。我添加了一种新方法,它似乎工作得更高效、更有效、更容易理解。你加入消极的前瞻/落后检查是正确的。忘记了OP不需要有3个空行。大概只需要5.012或5.010就可以说了-只是检查没有什么不微妙的事情。你正确地把消极的前瞻/落后检查。忘记了OP不需要3个空行。大概只需要5.012或5.010就可以了-只是检查没有什么不微妙的事情发生。