Regex 删除带有图案的线条,除非找到另一个图案?

Regex 删除带有图案的线条,除非找到另一个图案?,regex,perl,Regex,Perl,我有一个非常混乱的数据文件,看起来像这样 ======== Line 1 dfa====dsfdas== Line 2 df as TOTAL ============ 我想删除所有只有“=”的行,但如果TOTAL也在行中,则保留该行 我的代码如下: for my $file (glob '*.csv') { open my $in, '<', $file; my @lines; while (<$in>) { ne

我有一个非常混乱的数据文件,看起来像这样

========
Line 1
dfa====dsfdas==
Line 2 
df  as TOTAL ============
我想删除所有只有“=”的行,但如果TOTAL也在行中,则保留该行

我的代码如下:

for my $file (glob '*.csv') {
    open my $in, '<', $file;        
    my @lines;
    while (<$in>) {
        next if /===/; #THIS IS THE PROBLEM
        push @lines, $_;
    }   
    close $in;
    open my $out, '>', $file;
    print $out $_ for @lines;
    close $out;
}
next if /^=+$/;
用于我的$file(glob'*.csv'){
打开我的$in,,$file;
为@行打印$out$u;
收尾美元;
}
我想知道是否有一种方法可以在perl中使用正则表达式实现这一点。我想让“总计”成为条件1,让“==”成为条件2。然后,如果这两个条件都满足,脚本将单独保留该行,但如果只满足一个或零个条件,则删除该行


提前谢谢

您需要
\A
^
来检查字符串是否以
=
开头。放入类似regex的正则表达式:

next if /^===/;
或者,如果只存在
=
,则:

next if /^=+/;
它将跳过以
=
开头的所有行
+
用于匹配前一个令牌的一次或多次出现

编辑:

那么你应该用like


您需要
\A
^
来检查字符串是否以
=
开头。请输入类似以下的正则表达式:

next if /^===/;
或者,如果只存在
=
,则:

next if /^=+/;
它将跳过以
=
开头的所有行
+
用于匹配前一个令牌的一次或多次出现

编辑:

那么你应该用like


您可以使用否定的look-behind断言

next if/(?)


匹配
=
当前面没有TOTAL时,您可以使用否定的look-behind断言

next if/(?)


匹配
==
如果前面没有TOTAL

则当前正则表达式将拾取字符串中任何包含该字符串的内容

Hello===      Match
===goodbye    Match
=======       Match
foo======bar  Match
===           Match
=             No Match
Hello==       No Match
=========     Match
如果要确保它只拾取由
=
符号组成的字符串,则需要定位到行的开始和结束处,并考虑任何数量的
=
符号。将工作的正则表达式如下所示:

for my $file (glob '*.csv') {
    open my $in, '<', $file;        
    my @lines;
    while (<$in>) {
        next if /===/; #THIS IS THE PROBLEM
        push @lines, $_;
    }   
    close $in;
    open my $out, '>', $file;
    print $out $_ for @lines;
    close $out;
}
next if /^=+$/;
每个符号都表示:

^ The start of the string
= A literal "=" sign
+ One or more of the previous 
$ The end of the string
这将拾取从字符串开始到仅由
=
符号组成的字符串结束的任意长度的字符串

Hello===      No Match
===goodbye    No Match
=======       No Match
foo======bar  No Match
===           Match
=             Match
Hello==       No Match
=========     Match
我建议您仔细阅读perl的正则表达式以及每个符号的含义,如果您知道发生了什么,它将是一个非常强大的工具。

编辑: 如果要跳过与TOTAL和the=匹配的一行,只需进行两项检查:

next if(/TOTAL/ and /=+/)

这可能只需要一行正则表达式就可以完成。但是为什么要费心让它变得复杂和不那么可读呢?

您当前的正则表达式将在字符串中的任何位置拾取包含字符串的任何内容

Hello===      Match
===goodbye    Match
=======       Match
foo======bar  Match
===           Match
=             No Match
Hello==       No Match
=========     Match
如果要确保它只拾取由
=
符号组成的字符串,则需要定位到行的开始和结束处,并考虑任何数量的
=
符号。将工作的正则表达式如下所示:

for my $file (glob '*.csv') {
    open my $in, '<', $file;        
    my @lines;
    while (<$in>) {
        next if /===/; #THIS IS THE PROBLEM
        push @lines, $_;
    }   
    close $in;
    open my $out, '>', $file;
    print $out $_ for @lines;
    close $out;
}
next if /^=+$/;
每个符号都表示:

^ The start of the string
= A literal "=" sign
+ One or more of the previous 
$ The end of the string
这将拾取从字符串开始到仅由
=
符号组成的字符串结束的任意长度的字符串

Hello===      No Match
===goodbye    No Match
=======       No Match
foo======bar  No Match
===           Match
=             Match
Hello==       No Match
=========     Match
我建议您仔细阅读perl的正则表达式以及每个符号的含义,如果您知道发生了什么,它将是一个非常强大的工具。

编辑: 如果要跳过与TOTAL和the=匹配的一行,只需进行两项检查:

next if(/TOTAL/ and /=+/)

这可能只需要一行正则表达式就可以完成。但是为什么要费心让它变得复杂和不那么可读呢?

一般来说,你应该避免让你的正则表达式变得更复杂。将太多的东西压缩到一个正则表达式中可能看起来很聪明,但这会使它更难理解和调试

那么为什么不做一个复合条件呢

例如,像这样:

#!/usr/bin/env perl
use strict;
use warnings;

my @lines;
while (<DATA>) {
    next if ( m/====/ and not m/TOTAL/ );
    push @lines, $_;
}

print $_ for @lines;

__DATA__
========
Line 1
dfa====dsfdas==
Line 2 
df  as TOTAL ============
!/usr/bin/env perl
严格使用;
使用警告;
我的@行;
而(){
下一个if(m/=/而不是m/TOTAL/);
按@行,$\;
}
打印@行的美元;
__资料__
========
第1行
dfa===dsfdas==
第2行
df总计============

将跳过中包含
==
的任何行,只要它们不包含
TOTAL
。并且不需要高级正则表达式功能,我保证这会让您的维护程序员诅咒您。

作为一般规则,您应该避免使正则表达式变得更复杂。将太多内容压缩到单个正则表达式中可能看起来像c杠杆,但它使它更难理解,从而调试

那么为什么不做一个复合条件呢

例如,像这样:

#!/usr/bin/env perl
use strict;
use warnings;

my @lines;
while (<DATA>) {
    next if ( m/====/ and not m/TOTAL/ );
    push @lines, $_;
}

print $_ for @lines;

__DATA__
========
Line 1
dfa====dsfdas==
Line 2 
df  as TOTAL ============
!/usr/bin/env perl
严格使用;
使用警告;
我的@行;
而(){
下一个if(m/=/而不是m/TOTAL/);
按@行,$\;
}
打印@行的美元;
__资料__
========
第1行
dfa===dsfdas==
第2行
df总计============

将跳过中包含
==/code>的任何行,只要它们不包含
总计
。并且不需要高级正则表达式功能,我保证这会让维护程序员诅咒你。

你介意澄清这是什么吗?抱歉,我还是Perl的初学者。关键字^这是一个matchAh抱歉——有时我想删除的行不会以“=”开头。有时这是胡言乱语;我只想保留“总计”时的行是的。我将编辑这个问题。非常感谢您提供的解决方案——这非常有用!您介意澄清一下它的作用吗?对不起,我还是一个Perl初学者。关键字“^”表示行的开头。因此,如果行的开头是==这是一个matchAh抱歉——有时我希望删除的行不会以“=”开头。有时这是胡言乱语;我只想在其中包含“总计”的情况下保留该行。我将编辑该问题。非常感谢您提供的解决方案--这非常有帮助!因为您已经找到了答案,并且希望获得更多信息,您可以在此处查看此在线正则表达式测试程序,并解释:)