Perl regex: Come per afferrare la parte che è lo stesso
Domanda
Sto creando un sistema di scala per alcuni giochi e ho riscontrato un problema per quanto riguarda il sistema di base clan. Vedete, ogni giocatore che entra a far parte vengono analizzati e messi in una tabella i giocatori. In questo modo:
chelsea | gordon
chelsea | jim
chelsea | brad
OPPURE ...
CLANTAG|> jenna
CLANTAG|> jackson
CLANTAG|> irene
Quindi, quello che voglio: Voglio afferrare il CLANTAG, che è nello stesso luogo e identico in ogni nome i giocatori, che sono in quella squadra. Ma, il separatore potrebbe essere qualsiasi cosa, da spazi bianchi a nulla (clan player1, player2 clan o clanplayer1, clanplayer2).
Tutte le idee su come fare questo?
Grazie in anticipo.
Soluzione
Ecco un colpo:
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;
}
, che ha pronunciato la seguente:
C:\temp>perl test.pl
TEAM
TEAM|
TEAM |
TEAM
C:\temp>perl test.pl 1
TEAM
TEAM
TEAM
TEAM
C:\temp>
Altri suggerimenti
Facendo una pugnalata selvaggio qui, è questo che vuoi?
#! /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
A causa che genera:
tag=team1, name=foo
tag=team1, name=bar
tag=another, name=user
tag=another, name=player
tag=more, name=james
tag=more, name=brown
Modifica: rileggere domanda e commenti ..
Questo funziona per l'esempio, ma potrebbe non funzionare per i nomi con spazi o segni di punteggiatura, ed eventualmente altri scenari:
while ( <DATA> )
{
if ( /(\w+).*?(\w+)$/ )
{
print "$1, $2\n";
}
}
__DATA__
team1 | foo
team1 | bar
[another] . user
[another] . player
more-james
more-brown
si ottiene:
team1, foo
team1, bar
another, user
another, player
more, james
more, brown
Se si sta solo eseguendo l'espressione regolare sul nome di un giocatore alla volta, vorrei suggerire:
/(\w+)\W+(\w+)$/
In inglese, questo significa "almeno un carattere alfanumerico, seguito da almeno un carattere non-parola, seguito da almeno un carattere alfanumerico, e quindi la fine della linea"
"carattere di parola" è lettere, numeri e trattini. Quindi, se la gente mai usare qualcosa di diverso da quei personaggi nei loro tag / nick, avrà bisogno di modifica. Ad esempio, se la gente potrebbe anche avere trattini nei loro nick avresti bisogno:
/(\w+)\W+([\w-]+)$/
Per quanto ne so, la gente usa sempre caratteri di punteggiatura di tipo (e / o spazi bianchi) per la separazione tra loro clan e il loro nick, in modo che il \ W + ci dovrebbe andare bene.
Per quanto riguarda il caso avete dato senza separatore (clanplayer1, clanplayer2), non c'è modo per risolvere questo senza guardare i nomi più giocatori che si sa essere allo stesso clan, e capire a che punto i loro nomi iniziano a differiscono, quindi non può essere risolto con solo una regex.