Domanda

Sto tentando di analizzare una stringa come la seguente utilizzando un'espressione regolare .NET:

H3Y5NC8E-TGA5B6SB-2NVAQ4E0

e restituire quanto segue utilizzando Split:H3Y5NC8E TGA5B6SB 2NVAQ4E0

Convalido ogni carattere rispetto a un set di caratteri specifico (nota che le lettere "I", "O", "U" e "W" sono assenti), quindi utilizzare string.Split non è un'opzione.Il numero di caratteri in ciascun gruppo può variare e anche il numero di gruppi può variare.Sto usando la seguente espressione:

([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}-?){3}

Ciò corrisponderà esattamente a 3 gruppi di 8 caratteri ciascuno.Qualsiasi più o meno farà fallire la partita.Funziona nella misura in cui corrisponde correttamente all'input.Tuttavia, quando utilizzo il metodo Dividi per estrarre ciascun gruppo di caratteri, ottengo solo il gruppo finale.RegexBuddy si lamenta del fatto che ho ripetuto il gruppo di acquisizione stesso e che dovrei inserire un gruppo di acquisizione attorno al gruppo ripetuto.Tuttavia, nessuno dei miei tentativi in ​​tal senso ha raggiunto il risultato desiderato.Ho provato espressioni come questa:

(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){4}

Ma questo non funziona.

Dato che genero la regex nel codice, potrei semplicemente espanderla in base al numero di gruppi, ma speravo in una soluzione più elegante.


Tieni presente che il set di caratteri non include l'intero alfabeto.Fa parte di un sistema di attivazione del prodotto.Pertanto, tutti i caratteri che possono essere interpretati accidentalmente come numeri o altri caratteri vengono rimossi.per esempio.Le lettere 'I', 'O', 'U' e 'W' non sono presenti nel set di caratteri.

I trattini sono facoltativi poiché un utente non ha bisogno di digitarli, ma possono essere presenti se l'utente ha eseguito un copia e incolla.

È stato utile?

Soluzione 2

Ho scoperto la risposta che cercavo.Ecco il mio codice di lavoro:

    static void Main(string[] args)
    {
        string pattern = @"^\s*((?<group>[ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})-?){3}\s*$";
        string input = "H3Y5NC8E-TGA5B6SB-2NVAQ4E0";
        Regex re = new Regex(pattern);
        Match m = re.Match(input);

        if (m.Success)
            foreach (Capture c in m.Groups["group"].Captures)
                Console.WriteLine(c.Value);
    }

Altri suggerimenti

A proposito, puoi sostituire la classe di caratteri [ABCDEFGHJKLMNPQRSTVXYZ0123456789] con una classe di caratteri sottratti più leggibile.

[[A-Z\d]-[IOUW]]

Se vuoi solo abbinare 3 gruppi in questo modo, perché non usi questo modello 3 volte nella tua regex e usi semplicemente i sottogruppi 1, 2, 3 catturati per formare la nuova stringa?

([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}-([[A-Z\d]-[IOUW]]){8}

In PHP vorrei restituire (non so .NET)

return "$1 $2 $3";

Dopo aver esaminato la tua domanda e le risposte fornite, mi è venuto in mente questo:

RegexOptions options = RegexOptions.None;
Regex regex = new Regex(@"([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8})", options);
string input = @"H3Y5NC8E-TGA5B6SB-2NVAQ4E0";

MatchCollection matches = regex.Matches(input);
for (int i = 0; i != matches.Count; ++i)
{
    string match = matches[i].Value;
}

Poiché il "-" è facoltativo, non è necessario includerlo.Non sono sicuro per cosa stavi usando il {4} alla fine?Questo troverà le corrispondenze in base a ciò che desideri, quindi utilizzando MatchCollection puoi accedere a ciascuna corrispondenza per ricostruire la stringa.

Perché usare Regex?Se i gruppi sono sempre divisi da un -, non puoi usare Split()?

Scusa se non è quello che volevi, ma la tua stringa ha sempre il trattino che separa i gruppi, quindi invece di usare regex non potresti usare il metodo String.Split()?

Dim stringArray As Array = someString.Split("-")

Quali sono le caratteristiche distintive di un blocco valido?Avremmo bisogno di saperlo per poter essere davvero d'aiuto.

Il mio suggerimento generico, convalida il set di caratteri in un primo passaggio, quindi dividi e analizza in un metodo separato in base a ciò che ti aspetti.Se si trova in un sito Web/app, è possibile utilizzare la convalida ASP Regex sul front-end e quindi suddividerla sul back-end.

Se stai solo controllando il valore del gruppo, con group(i).value, otterrai solo l'ultimo.Tuttavia, se desideri enumerare tutte le volte in cui il gruppo è stato catturato, utilizza group(2).captures(i).value, come mostrato di seguito.

system.text.RegularExpressions.Regex.Match("H3Y5NC8E-TGA5B6SB-2NVAQ4E0","(([ABCDEFGHJKLMNPQRSTVXYZ0123456789]+)-?)*").Groups(2).Captures(i).Value

Mike,

Puoi utilizzare il set di caratteri di tua scelta all'interno del gruppo di caratteri.Tutto ciò che serve è aggiungere il modificatore "+" per acquisire tutti i gruppi.Vedi la mia risposta precedente, cambia semplicemente [A-Z0-9] con quello che ti serve (ad es.[ABCDEFGHJKLMNPQRSTVXYZ0123456789])

Puoi usare questo modello:

Regex.Split("H3Y5NC8E-TGA5B6SB-2NVAQ4E0", "([ABCDEFGHJKLMNPQRSTVXYZ0123456789]{8}+)-?")

Ma dovrai filtrare le stringhe vuote dall'array risultante.Citazione da MSDN:

Se più corrispondenze sono adiacenti, nell'array viene inserita una stringa vuota.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top