Perl Regex测试数组是否统一

时间:2017-03-20 10:52:23

标签: regex perl regex-lookarounds regex-greedy regex-group

我有一段不起作用的代码,我无法弄清楚原因。 这可能是一个正则表达式问题,但据我所知它应该有效。

我有一个包含<typenumber>:<KitName>的数组,例如2:K1663

我想将此数组中每个条目的KitName与第一个条目的KitName相匹配。为此我有一个正则表达式,它应该返回冒号:之后的所有内容。然后,我使用if将当前条目$_与第一个条目$KitHit[0]进行比较。

然后,如果有任何不匹配,$booly将被设置为1并且所有条目都将被打印。

然而,即使套件完全相同,我仍然会打印条目。 我添加了print "A"print "B"以查看匹配代码何时以及何时运行不匹配代码。这将返回B A B A B A B A B而不考虑我的数据。

谁能告诉我出了什么问题?无论我尝试什么,我都无法理解。

my @KitHold;
my $booly = 0;

open( $outputfile_fh, ">>", $outputfile ) or die "Could not open file     '$outputfile' $!";    

foreach ( (), @KitHit ) {

    my $KitHelp;

    if ( ( $_ =~ /(?<=:)\w+/g ) eq ( $KitHit[0] =~ /(?<=:)\w+/g ) ) {
        $KitHelp = $separator[$1] . "\[$categories[$1]\]:" . $_ . "\n" if $_ =~ /(\d+)/;
        push (@KitHold,$KitHelp);
        print "\nA;
    }
    else {
        $KitHelp = $separator[$1] . "\[$categories[$1]\]:" . $_ . "\n" if $_ =~ /(\d+)/;
        push( @KitHold, $KitHelp );
        $booly = 1;
        print "\nB";
    }
}

if ( $booly == 1 ) {
    print {$outputfile_fh} "\n\nKits not uniform:\n@KitHold";
} 

close $outputfile_fh;

示例数据:

@KitHit不匹配:

    2:K1663
    3:K1675
    4:K1663
    5:K1663
    6:K1663
    7:K1663
    8:K1675
    13:K1675
    14:K1675
带有统一条目的

@KitHit

    2:K1663
    3:K1663
    4:K1663
    5:K1663
    6:K1663
    7:K1663
    8:K1663
    13:K1663
    14:K1663

我还应该提一下,Kit名称最终可能包含的不仅仅是K和4个数字,因此我的正则表达式会查看冒号之后的所有内容。

4 个答案:

答案 0 :(得分:2)

因此,如果我正确地阅读了您 - 您正在尝试检查所有&#34; K&#34;数字是否相同。

我实际上建议一个&#34;魔法正则表达式&#34;这里不是解决方案 - 它是可行的,但它不可避免地会很难遵循,以后很难修改。

相反,我说你的数据非常适合插入perl中的hash,因为......好吧,键值对,那就是哈希是给。

因此,考虑到这一点,我会像这样解决它:

var app = angular.module('MyApp', ['ngDialog','chatSocket']);

app.controller('msgController', function ($scope, socket) {
$scope.socket = socket;
$scope.submit = function () {
    socket.send($scope.msgbox);
};  
});

我在这里假设您可以从文件中读取。如果这不是一个有效的假设,那么您可以使用#!/usr/bin/env perl use strict; use warnings; use Data::Dumper; #read it into a hash my %data = map { /(\d+):(\w+)/ } <>; # <> is the magic file handle, that reads 'STDIN' #or files specified to command line. #you can do the same with any FH that you've opened though. #for debug print Dumper \%data; #count values. my %count_of; $count_of{$_}++ for values %data; #for debug print Dumper \%count_of; #if there's more than one key here, we #have a mismatch if ( keys %count_of > 1 ) { print "Mismatch spotted:\n"; foreach my $key ( sort { $a <=> $b} keys %data ) { print "$key:$data{$key}\n"; } } 和地图执行相同的操作:

@KitHit

做同样的事情。

答案 1 :(得分:1)

为什么不用仅使用正则表达式的解决方案来实现结果?

\A\s*(?>[^\s:]+:(?(1)\1|(\S+))\s*)+\z

Live demo(没有不匹配)

Live demo(不匹配)

答案 2 :(得分:1)

你的考试

if ( ( $_ =~ /(?<=:)\w+/g ) eq ( $KitHit[0] =~ /(?<=:)\w+/g ) ) {

正在比较两个正则表达式模式匹配的结果。这些结果是字符串是否与模式匹配的布尔指示

您正在测试数组中的值是否包含冒号:,后跟至少一个&#34; word&#34;字符。由于他们都这样做,两次匹配的结果将始终为1.您的比较比较'1' eq '1'并始终导致 true

您的代码存在许多其他问题

  • 您应该显示minimal, complete and verifiable example,以便我们自行尝试您的代码

  • 您必须在您编写的每个Perl程序的顶部use strictuse warnings 'all',并使my的每个变量尽可能接近其第一个使用点< / p>

  • 大多数Perl程序员更熟悉用小写字母,数字和下划线命名的词法变量。避免首字母大写特别重要。因此@KitHit应为@kit_hit

  • 您可以在程序开头直接打开输出文件,但不要写入它直到结束。你的意思是打开追加吗?

  • foreach ( (), @KitHit ) {行中,()无效,应删除

  • 您在$KitHelp的两个分支中同等地计算@KitHoldif。这些应该在if

  • 之前或之后单独完成一次
  • 您应该使用变量插值来构建字符串,而不是连接运算符.。另请注意,方括号不需要在双引号内转义,所以

     $KitHelp = $separator[$1] . "\[$categories[$1]\]:" . $_ . "\n"
    

    可以写成

     $KitHelp = "$separator[$1][$categories[$1]]:$_\n"
    
  • 您的标志变量$booly应该有更有意义的名称,例如$mismatch

您还没有显示@separator@categories的内容,因此我无法正确测试此代码,但它看起来是正确的并且已编译

use strict;
use warnings 'all';

my @hit_hold;
my (@separator, @categories);    # Need initialising

my @kit_hit = qw/
    2:K1663
    3:K1675
    4:K1663
    5:K1663
    6:K1663
    7:K1663
    8:K1675
    13:K1675
    14:K1675
/;

my $mismatch;

my ($output_file) = @ARGV;    # Take output file name from command line

die unless my ($n0, $key0) = $kit_hit[0] =~ /^(\d+):(.+)/;

for ( @kit_hit ) {

    next unless my ($n, $key) = /^(\d+):(.+)/;

    push @hit_hold, "$separator[$n][$categories[$1]]:$_\n";

    if ( $key eq $key0 ) {
        print "\nA";
    }
    else {
        $mismatch = 1;
        print "\nB";
    }
}

if ( $mismatch ) {

    open my $out_fh, '>', $output_file or die qq{Could not open "$output_file" for output: $!};    
    my $old_fh = select $out_fh;

    print "\n\n";
    print "Kits not uniform:\n";
    print "$_\n" for @hit_hold;
    close $out_fh;

    select $old_fh;
} 

答案 3 :(得分:0)

您可以尝试以下方法将每个值与第一个值匹配。

说,第一个值是:

K1663

然后,您可以遍历其余索引并应用此正则表达式来确定它是否匹配。如果是匹配则可以打印出来。

use strict;


my $regex = qr/^(\d+):(?!K1663$)(.*)$/mp;

my $str = '3:K1675';
# your loop goes here : where each $str contains the current index value
if( $str =~ /$regex/g )
  print "$1 $2 \n";

Regex Demo

Demo Impl