2010-06-15 7 views
0

Mes compétences regex ne sont pas très bons et récemment un nouvel élément de données a jeté mon analyseur dans une boucleParsing chaîne complexe en utilisant des expressions régulières

Prenez la chaîne suivante

« + USER = Bob Smith-GROUP = Administrateur + FONCTION = lecture/FONCTION = Write »

Auparavant, j'avais les éléments suivants pour mon regex: [+ \\ - /]

qui tournerait le résultat dans

USER = Bob Smith
GROUP = Administrateur
FONCTION = Lire
FONCTION = Ecrire
FONCTION = Lire

Mais maintenant, j'ai des valeurs avec des tirets dans les qui est à l'origine une mauvaise sortie

chaîne New ressemble « + USER = Bob Smith-GROUP = Admin + FONCTION = Read/FUNCTION = Write/FUNCTION = Read-Write "

Ce qui me donne le résultat suivant, et casse la structure clé = valeur.

USER = Bob Smith
GROUP = Administrateur
FONCTION = Lire
FONCTION = écriture
FONCTION = Lire
Ecrire

quelqu'un peut me aider à formuler une regex valable pour la manipulation de ce ou moi de signaler quelques exemples de clé/valeur. Fondamentalement, je dois être capable de gérer les signes + -/afin d'obtenir des combinaisons.

+1

Lorsque vos valeurs de données peuvent contenir vos délimiteurs regex va compliquer considérablement la situation. Avez-vous un contrôle sur la façon dont les données vous parviennent? –

+0

Malheureusement, les données proviennent de nombreuses sources différentes dont je n'ai pas le contrôle. –

+0

Serait-il plus facile de chercher les clés que vous cherchez plutôt que les séparateurs? Recherchez "Utilisateur", "Groupe" et "Fonction" et analysez les résultats correspondants? – AllenG

Répondre

0

Vous n'avez pas spécifié le moteur regex que vous utilisez, mais cela fonctionne si vous avez lookahead/lookbehind.

Cela fonctionne sur le principe que les clés sont toutes majuscules seulement, alors que les valeurs ne sont pas - pas sûr si c'est une hypothèse valide, mais si ce n'est pas le cas, les choses se compliqueront.

(?<=[+-\/])[A-Z]+=(?:(?![A-Z]+=)[^=])+(?=[+-\/]|$) 


Et voici ma tentative d'expliquer que (ne sais pas à quel point cela a un sens):

(?x)   # enable regex comment mode 
(?<=[+-\/]) # start with one of the delimiters, but excluded from match 
[A-Z]+  # match one or more uppercase (for the key) 
=   # match the equal sign 

(?:   # start non-capturing group 

    (?!   # start negative lookahead, to prevent keys matching 
    [A-Z]+=  # a key and equals (since in negative lookahead, this is what we exclude) 
)   # end the negative lookahead 
    [^=]   # match a character that's not = 

)+   # end non-capturing group, match one or more times, until... 

(?=[+-\/]|$) # next char must be delimiter or end of line for match to succeed 


Pour Java string-> regex, antislashs besoin s'échapper (comme les citations, s'il y en a):

Pattern p = Pattern.compile("(?<=[+-\\/])[A-Z]+=(?:(?![A-Z]+=)[^=])+(?=[+-\\/]|$)"); 


Et si les groupes de capture sont nécessaires, il suffit d'ajouter parens autour des parties appropriées:

Pattern p = Pattern.compile("(?<=[+-\\/])([A-Z]+)=((?:(?![A-Z]+=)[^=])+(?=[+-\\/]|$))"); 


La partie correspondante de celui-ci, pour la transformer en newline texte délimité, est quelque chose comme ...

Matcher m = p.Matcher(InputText); 
StringBuffer Result = new StringBuffer(""); 

while (m.find()) 
{ 
    Result.append(m.Group() + "\n"); 
} 
+0

Désolé j'utilise le modèle Java pour exécuter l'expression régulière Motif p = Pattern.compile ("[+ \\ - /]"); Les valeurs peuvent être majuscules ou minuscules, je n'ai aucun problème à les retourner pour être un cas cependant. –

+0

Eh bien, si vous pouvez forcer la clé et la valeur à toujours être différent cas, cela vous permet de différencier, ce qui signifie qu'il est possible. Pour utiliser l'expression ci-dessus en Java, doublez simplement tous les '\' s. –

+0

hhmm malheureusement, je suis incapable de faire fonctionner cela, il semble fonctionner dans mon testeur de regex, mais dans le code java, les résultats sont géniaux pour dire le moins. Je ne sais pas si j'ai la bonne échappée là où c'est nécessaire –

0

Basé sur votre deuxième exemple, cette regex: (\w+)=([\w|-|\s]+) retourne ces résultats:

USER=Bob Smith 
GROUP=Admin 
FUNCTION=Read 
FUNCTION=Write 
FUNCTION=Read-Write 

La parenthèse fournir des regroupements pour chaque élément, de sorte que chaque match contiendra deux groupes, le premier aura la partie avant que = (donc USER GROUP, FONCTION) et le second aura la valeur (Bob Smith, admin, lecture, écriture, lecture-écriture)

vous pouvez également nommer les groupes si ce serait plus facile:

(?<funcrion>\w+)=(?<value>[\w|-|\s]+) 

Ou si vous ne se soucient pas des groupes, vous pouvez supprimer les parens altoge Ther

\w+=[\w|-|\s]+ 
+0

Les trucs de groupe nommés ne fonctionneront pas, c'est la syntaxe .NET seulement. –

+2

Oh, et cette regex est fausse - vous ne pouvez pas utiliser l'alternance dans une classe de caractères - vous voudriez soit ((?: \ W | - | \ s) +) 'ou' ([\ w \ - \ s] +) '- sauf que cela ajoute incorrectement la clé GROUP à la valeur USER. –

+0

Cela semble me donner les négatifs des valeurs, comment puis-je inverser cela pour obtenir la combinaison clé = valeur plutôt que les signes = ou -? –

0

Une autre option, si vous avez un nombre limité de touches, vous pouvez simplement correspondre:


qui en Java je probablement mettre en œuvre comme ceci:

String Key = "USER|GROUP|FUNCTION" ; 
String Delim = "[+-\\/]"; 
Pattern p = Pattern.compile("(?<="+Delim+")("+Key+")=[^=]+(?=$|"+Delim+"(?:"+Key+"))"); 

Cela dépend, par exemple, de "Write" n'étant pas une clé valide (et si vous pouvez forcer t Le cas des clés pour être soit "écrire" soit "ÉCRIRE" alors ça veut dire que ça va marcher).


La partie correspondante de ce fait, pour le transformer en texte délimité par saut de ligne, est quelque chose comme ...

Matcher m = p.Matcher(InputText); 
StringBuffer Result = new StringBuffer(""); 

while (m.find()) 
{ 
    Result.append(m.Group() + "\n"); 
} 
0

Si vous délimitant des champs avec des caractères qui peuvent apparaître dans les valeurs, t'es foutu.

Supposons que vous recevez une chaîne comme:

one=a-two=b-three=c-d-four=e 

Si cela devait analyser dans tout cela?

one=a 
two=b 
three=c-d 
four=e 

Ou devrait-il analyser cela?

one=a 
two=b 
three=c 
d-four=e 

Comment le savez-vous? Quelle est votre base pour décider cela?

Questions connexes