【问题标题】:Perl regex: How to grab the part that is the samePerl 正则表达式:如何抓取相同的部分
【发布时间】:2009-02-21 03:45:36
【问题描述】:

我正在为一些游戏创建天梯系统,但我遇到了关于氏族基础系统的问题。你看,每个加入的玩家都会被解析并放入玩家表中。像这样:

chelsea | gordon 
chelsea | jim
chelsea | brad

或者...

CLANTAG|> jenna
CLANTAG|> jackson
CLANTAG|> irene 

所以,我想要的是:我想抓住 CLANTAG,它在同一个地方,并且在该团队中的每个球员的名字都相同。但是,分隔符可以是从空白到无的任何内容(clan player1、clan player2 或 clanplayer1、clanplayer2)。

关于如何做到这一点的任何想法?

提前致谢。

【问题讨论】:

  • 所以这里的团队名称是“team1”、“another”和“more”?我认为问题是每个人都使用了不同的格式,还是有少数可能性?
  • 请稍微澄清一下这个问题 - 目前尚不清楚您要捕获哪些数据。
  • 是的;请显示示例输入和您想要发生的事情。即“给定 {foo}{bar},我想要数组 [qw/foo bar/]”。然后我们可以提供帮助。
  • 是的,分隔符会有所不同,就像我在下面的评论中所写的那样,它可以是从空白到空的所有内容。我想获取 TAG,而不是玩家名称。就像 TEAMplayer1 和 TEAMplayer2 一样,我想抢 TEAM。使用标签-用户,标签-用户2,我想抓住“标签”。

标签: regex perl pcre


【解决方案1】:

这是一个镜头:

use strict;
use warnings;

my($strip) = shift || 0;

print FindTeamName("TEAMJimBob", "TEAMJoeBob", "TEAMBillyBob"), "\n";
print FindTeamName("TEAM|JimBob", "TEAM|JoeBob", "TEAM|BillyBob"), "\n";
print FindTeamName("TEAM | JimBob", "TEAM | JoeBob", "TEAM | BillyBob"), "\n";
print FindTeamName("TEAMJimBob", "TEAM|JoeBob", "TEAM - BillyBob"), "\n";

sub FindTeamName
{
    my(@players) = @_;

    my($team) = shift;
    foreach my $player (@players) {
        $team = FindCommonString($team, $player);
    }

    $team =~ s{\W+$}{} if $strip;

    $team;
}

sub FindCommonString
{
    my($str1, $str2) = @_;

    my(@arr1) = split(//, $str1);
    my(@arr2) = split(//, $str2);

    my($common) = "";

    while (@arr1 && @arr2) {
        my($letter1) = shift(@arr1);
        my($letter2) = shift(@arr2);

        if ($letter1 eq $letter2) {
            $common .= $letter1;
        }
        else {
            last;
        }
    }

    $common;
}

给出以下内容:

C:\temp>perl test.pl
TEAM
TEAM|
TEAM |
TEAM

C:\temp>perl test.pl 1
TEAM
TEAM
TEAM
TEAM

C:\temp>

【讨论】:

    【解决方案2】:

    在这里大放异彩,这是你想要的吗?

    #! /usr/bin/perl
    
    use strict;
    use warnings;
    
    while (<DATA>)
    {
      if (/^(\w+) \| (\w+)$/     ||
          /^\[(\w+)\] \. (\w+)$/ ||
          /^(\w+)-(\w+)$/)
      {
        print "tag=$1, name=$2\n";
      }
    }
    
    exit 0;
    
    __DATA__
    team1 | foo
    team1 | bar
    
    [another] . user
    [another] . player
    
    more-james
    more-brown
    

    因为它生成:

    tag=team1, name=foo
    tag=team1, name=bar
    tag=another, name=user
    tag=another, name=player
    tag=more, name=james
    tag=more, name=brown
    

    【讨论】:

    • 不完全是,因为分隔符不同。它可以是从空白到什么都没有的任何东西,就像 TEAMplayer1、TEAMplayer2 一样。而且我还想获​​取 TAG,而不是玩家名称。 :)
    • 好的,如果您对格式更具体一点,答案会更接近您的需要。
    • 格式?就像我说的,它可以是一切,我们唯一知道的是它是每个团队成员名字的平等部分。
    • 啊,我明白了 - 您正在左侧寻找多行通用的东西。这有点难......
    • 是的,有可能。您只需要在任意行组之间寻找最左边最长的公共子字符串。不过这并不容易。
    【解决方案3】:

    编辑:重新阅读问题和 cmets..

    这适用于示例,但可能不适用于带有空格或标点符号的名称,以及可能的其他情况:

    while ( <DATA> )
    {
        if ( /(\w+).*?(\w+)$/ )
        {
            print "$1, $2\n";
        }
    }
    
    
    __DATA__
    team1 | foo
    team1 | bar
    
    [another] . user
    [another] . player
    
    more-james
    more-brown
    

    给予:

    team1, foo
    team1, bar
    another, user
    another, player
    more, james
    more, brown
    

    【讨论】:

    • 啊,错过了无分隔符的情况。如果您有teamjones 和teamjoe,则无法知道团队名称是“team”、“teamj”、“teamjo”等。
    • 这还不错,事实上,这对我存储在数据库中的每个团队都有效。如果我们可能会为此添加一点故障保护,它可能正是我所需要的...... :) 谢谢
    【解决方案4】:

    如果您一次只对一个玩家的名字运行正则表达式,我建议:

    /(\w+)\W+(\w+)$/
    

    在英文中,这意味着“至少一个单词字符,后跟至少一个非单词字符,后跟至少一个单词字符,然后是行尾”

    “单词字符”是字母、数字和下划线。因此,如果人们在他们的标签/昵称中使用了这些字符以外的任何内容,则需要对其进行修改。例如,如果人们的昵称中可能还有连字符,您需要:

    /(\w+)\W+([\w-]+)$/
    

    据我所知,人们总是使用标点符号(和/或空格)来区分他们的氏族和昵称,所以那里的 \W+ 应该没问题。

    至于你给出的没有分隔符的情况(clanplayer1,clanplayer2),如果不查看你知道在同一个氏族中的多个玩家的名字,并弄清楚他们的名字从什么时候开始,就无法解决这个问题不同,所以不能单独用正则表达式解决。

    【讨论】:

    • 我认为他想派生团队名称,因此对于“fooA”和“fooB”,他希望提取“foo”,即最左边的最长共性,当然忽略任何格式/分隔符垃圾。
    猜你喜欢
    • 2013-09-27
    • 2012-02-25
    • 2017-04-24
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多