Регулярное выражение Perl:Как захватить ту часть, которая является такой же
Вопрос
Я создаю систему лестниц для некоторых игр, и я столкнулся с проблемой, связанной с системой клановой базы.Видите ли, каждый игрок, который присоединяется, анализируется и заносится в таблицу игроков.Вот так:
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), нет способа решить эту проблему, не посмотрев на имена нескольких игроков, которые, как вы знаете, принадлежат к одному клану, и не выяснив, в какой момент их имена начинают отличаться, поэтому ее нельзя решить одним регулярным выражением.