【问题标题】:Regex match on whole .csv file整个 .csv 文件的正则表达式匹配
【发布时间】:2016-11-18 18:28:27
【问题描述】:

早安!

我正在努力解决一个问题,我从没想过会是一个问题。我有一个带有分隔符 ;.csv 文件,我想检查它的语法。它看起来像这样:

wellenname;tag
Welle A;01/02/2016
Welle B3;14/11/2016
server;welle
server5name032;Welle B3 Rand
server3name01;Welle A
server2name;Welle B3

所以我有一个格式精美的 .csv 文件,我可以使用正则表达式对其进行处理。因此,我为正则表达式构建了四种情况:

  1. wellenname;标签\n
  2. (Welle [A-Z]+[0-9]*;\d{2}/\d{2}/\d{4}\n)+
  3. 服务器;很好\n
  4. (\S*;Welle [a-z,A-Z,0-9]+( 兰德)(\n))+

这在名为 The Regex Coach 的工具中工作得非常漂亮,它基本上试图匹配一个正则表达式和一个字符串,并在它遇到困难的地方输出。

然后我把它放在 Perl 中。读取文件并检查语法:

use strict;
use warnings;
use Data::Dumper;
my $filename = 'theFile.csv';

my $content;

open(my $fh, '<', $filename) or die "Could not open file $filename $!";
$content = join('',<$fh>);

if ($content =~ /wellenname;tag\n(Welle [A-Z]+[0-9]*;\d{2}\/\d{2}\/\d{4}\n)+server;welle\n(\S*;Welle [a-z,A-Z,0-9]+( Rand)*(\n)*)+/) { 
  print "Syntax seems to be valid!";

}else{
  print "You have syntax errors!";
}

我逐行浏览了文件,但即使我每个部分只插入一个条目,它也会失败。 (或更好:它跳转到 else 并打印字符串)

我是不是忘了某事。还是我的想法有市长错误? 如果有人能给我提示,我会很高兴!

【问题讨论】:

    标签: regex perl csv


    【解决方案1】:

    嗯,这确实有效:

    use strict;
    use warnings;
    use Data::Dumper;
    
    my $content = join('',<DATA>);
    
    if ($content =~ /wellenname;tag\n(Welle [A-Z]+[0-9]*;\d{2}\/\d{2}\/\d{4}\n)+server;welle\n(\S*;Welle [a-z,A-Z,0-9]+( Rand)*(\n)*)+/) {
      print "Syntax seems to be valid!";
    } else {
      print "You have syntax errors!";
    }
    
    __DATA__
    wellenname;tag
    Welle A;01/02/2016
    Welle B3;14/11/2016
    server;welle
    server5name032;Welle B3 Rand
    server3name01;Welle A
    server2name;Welle B3
    

    您的文件可能有问题。当它是 Windows 生成的文件时,您可能必须搜索 \r\n 而不是 \n

    但是你的正则表达式仍然不完美。

    首先,您在正则表达式的开头和结尾分别错过了^$。现在它可以将 CSV 与实际 CSV 之前和之后的额外符号匹配。其次,[] 中不需要逗号,所以[a-z,A-Z,0-9] 应该是[a-zA-Z0-9](或者它会匹配, 以及您指定的其他符号)。此外,您应该考虑使用/x 开关(使您的正则表达式更具可读性)并使用m{...} 而不是/.../,以免在正则表达式内部转义/

    所以,我的最终版本是:

    use strict;
    use warnings;
    
    my $content = join('',<DATA>);
    
    if (
        $content =~ m{
            ^
            wellenname;tag\n
            (Welle[ ][A-Z]+[0-9]*;\d{2}/\d{2}/\d{4}\n)+
            server;welle\n
            (\S*;Welle[ ][a-z,A-Z,0-9]+([ ]Rand)*(\n)*)+
            $
        }x
    ) {
      print 'Syntax seems to be valid!';
    }
    else {
      print 'You have syntax errors!';
    }
    
    __DATA__
    wellenname;tag
    Welle A;01/02/2016
    Welle B3;14/11/2016
    server;welle
    server5name032;Welle B3 Rand
    server3name01;Welle A
    server2name;Welle B3
    

    请注意,我在使用 /x 时使用 [ ] 来匹配空间。我还使用'...' 而不是"...",因为我们不需要在该字符串中启用插值。

    【讨论】:

    • 你间接解决了这个问题!提示要更仔细地检查我的文件,我注意到 .csv 是一个 Windows 样式的文件,所以我必须搜索 \r\n 而不仅仅是 \n!当我尝试您的(工作!)示例时,我检查了文件的编码和...是的,也许是新手错误,但实际上是解决方案;)您的提示非常有帮助!谢谢!
    • 再次感谢,我尝试了 m{} 和 /x,它们工作得很好。在[ ] 中省略, 使其实际上也更具可读性。
    • , in [] 意味着它也将匹配 ,不是你想要的
    • 是的,我就是这么认为的。实际上,我将, 放在了这些值之间,因为我只是输入了我在纸上构建的正则表达式,而没有考虑正则表达式的 perl 语法。感谢您的建议!
    猜你喜欢
    • 2019-09-07
    • 2011-05-15
    • 1970-01-01
    • 2016-06-18
    • 2010-11-15
    • 2012-01-06
    • 1970-01-01
    相关资源
    最近更新 更多