Регулярное выражение Perl:Как захватить ту часть, которая является такой же

StackOverflow https://stackoverflow.com/questions/572160

  •  05-09-2019
  •  | 
  •  

Вопрос

Я создаю систему лестниц для некоторых игр, и я столкнулся с проблемой, связанной с системой клановой базы.Видите ли, каждый игрок, который присоединяется, анализируется и заносится в таблицу игроков.Вот так:

chelsea | gordon 
chelsea | jim
chelsea | brad

или...

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

Итак, чего я хочу:Я хочу захватить значок КЛАНА, который находится в том же месте и идентичен именам всех игроков, которые есть в этой команде.Но разделителем может быть что угодно, от пробела до ничего (игрок клана 1, игрок клана 2 или игрок клана 1, игрок клана 2).

Есть какие-нибудь идеи о том, как это сделать?

Заранее благодарю.

Это было полезно?

Решение

Вот такой снимок:

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>

Другие советы

Совершая дикий удар здесь, это то, чего ты хочешь?

#! /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

Редактировать:перечитайте вопрос и комментарии..

Это работает для примера, но может не сработать для имен с пробелами или пунктуацией и, возможно, в других сценариях:

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

Если вы просто запускаете регулярное выражение для имени одного игрока за раз, я бы предложил:

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

В английском языке это означает "по крайней мере, один словесный символ, за которым следует по крайней мере один несловесный символ, за которым следует по крайней мере один словесный символ, а затем конец строки".

"Символ слова" - это буквы, цифры и подчеркивания.Так что, если люди когда-либо будут использовать что-либо, кроме этих символов, в своих тегах / никах, это потребует модификации.Например, если у людей также могут быть дефисы в их никах, вам понадобится:

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

Насколько я знаю, люди всегда используют знаки препинания (и / или пробелы) для разделения между своим кланом и своим ником, поэтому \W + там должно быть в порядке вещей.

Что касается случая, который вы привели без разделителя (clanplayer1, clanplayer2), нет способа решить эту проблему, не посмотрев на имена нескольких игроков, которые, как вы знаете, принадлежат к одному клану, и не выяснив, в какой момент их имена начинают отличаться, поэтому ее нельзя решить одним регулярным выражением.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top