aiuto Regex: Il mio modello regex corrisponderà stringhe non valide
-
22-09-2019 - |
Domanda
La stringa di testo che voglio per convalidare è costituito da quello che io chiamo "segmenti". Un singolo segmento potrebbe essere simile a questo:
[A-Z,S,3]
Finora sono riuscito a costruire questo schema di espressione regolare
(?:\[(?<segment>[^,\]\[}' ]+?,[S|D],\d{1})\])+?
funziona, ma tornerà partite, anche se l'intera stringa di testo contiene testo non valido. Credo che ho bisogno di usare ^
e $
qualche parte nel mio modello, ma io non riesco a capire come!?
Vorrei che il mio modello per produrre i seguenti risultati:
-
[A-Z,S,3][A-Za-z0-9åäöÅÄÖ,D,4]
OK (due segmenti) -
[A-Z,S,3]aaaa[A-Za-z0-9åäöÅÄÖ,D,4]
Nessuna corrispondenza -
crap[A-Z,S,3][A-Za-z0-9åäöÅÄÖ,D,4]
Nessuna corrispondenza -
[A-Z,S,3][]
Nessuna corrispondenza -
[A-Z,S,3][klm,D,4][0-9,S,1]
OK (tre segmenti)
Soluzione
Usa ^ per ancorare l'inizio e $ per l'ancoraggio alla fine. Es .: ^(abc)*$
, questo corrisponde a zero o più ripetizioni del gruppo ( "abc" in questo esempio) e che deve iniziare all'inizio della stringa di input e terminano alla fine di esso.
^(?:[(?[^,][}' ]+?,[S|D],\d{1})])+$
-utilizzando un +?
ungreedy non importa, come si richiede in modo che corrisponda fino alla fine in ogni caso. Tuttavia, il vostro regex ha alcuni problemi.
^(?:\[[^,]+,[SD],\d\])+$
-sembra più simile a ciò che si desidera.
- non ho potuto decifrare ciò che si intende per la prima parte, quindi il mio regex è più generale di quanto richiesto,
[^,]+,
corrisponderà a qualsiasi sequenza di non-virgole seguito da una virgola, e in effetti si dovrebbe probabilmente aggiungere]
a questa negata classe di caratteri. -
[S|D]
è una classe di caratteri di tre personaggi, come|
non significa alternanza qui ((S|D)
significherebbe lo stesso[SD]
però). -
{1}
è l'impostazione predefinita per qualsiasi atomo, non è necessario specificarlo.
Pseudocodice (eseguirlo a codepad.org ):
import re
def find_segments(input_string):
results = []
regex = re.compile(r"\[([^],]+),([SD]),(\d)\]")
start = 0
while True:
m = regex.match(input_string, start)
if not m: # no match
return None # whole string didn't match, do another action as appropriate
results.append(m.group(1, 2, 3))
start = m.end(0)
if start == len(input_string):
break
return results
print find_segments("[A-Z,S,3][klm,D,4][0-9,S,1]")
# output:
#[('A-Z', 'S', '3'), ('klm', 'D', '4'), ('0-9', 'S', '1')]
La grande differenza qui è l'espressione corrisponde solo la parte completa [...]
, ma viene applicato in successione, quindi devono ricominciare dove gli ultimi estremità (o estremità alla fine della stringa).
Altri suggerimenti
Si desidera qualcosa di simile:
/^(\[[^],]+,[SD],\d\])+$/
Ecco un esempio di come si potrebbe usare questa espressione regolare in C #:
using System;
using System.Text.RegularExpressions;
class Program
{
static void Main(string[] args)
{
string[] tests = {
"[A-Z,S,3][A-Za-z0-9,D,4]",
"[A-Z,S,3]aaaa[A-Za-z0-9,D,4]",
"crap[A-Z,S,3][A-Za-z0-9,D,4]",
"[A-Z,S,3][]",
"[A-Z,S,3][klm,D,4][0-9,S,1]"
};
string segmentRegex = @"\[([^],]+,[SD],\d)\]";
string lineRegex = "^(" + segmentRegex + ")+$";
foreach (string test in tests)
{
bool isMatch = Regex.Match(test, lineRegex).Success;
if (isMatch)
{
Console.WriteLine("Successful match: " + test);
foreach (Match match in Regex.Matches(test, segmentRegex))
{
Console.WriteLine(match.Groups[1]);
}
}
}
}
}
Output:
Successful match: [A-Z,S,3][A-Za-z0-9,D,4]
A-Z,S,3
A-Za-z0-9,D,4
Successful match: [A-Z,S,3][klm,D,4][0-9,S,1]
A-Z,S,3
klm,D,4
0-9,S,1