2010-10-06 4 views
9

chaîne à diviserdécoupant une chaîne qui a séquence d'échappement en utilisant l'expression régulière en Java

abc:def:ghi\:klm:nop 

chaîne doit être divisé en fonction de « : » « \ » est échapper à caractère. Donc "\:" ne devrait pas être traité comme un jeton.

split (":") donne

[abc] 
[def] 
[ghi\] 
[klm] 
[nop] 

sortie requise est un tableau de chaîne

[abc] 
[def] 
[ghi\:klm] 
[nop] 

Comment le \: être ignoré

+0

Est-ce que ce qui suit est également possible: 'abc:" def: ghi ": jkl'? –

Répondre

16

Utilisez un look-behind assertion:

split("(?<!\\\\):") 

Ceci ne correspondra que s'il n'y a pas de \ précédent. L'utilisation de l'échappement double \\\\ est requise, car l'une est requise pour la déclaration de chaîne et l'autre pour l'expression régulière. Notez cependant que cela ne vous permettra pas d'échapper les barres obliques inverses, dans le cas où vous voulez permettre à un jeton de se terminer par une barre oblique inverse (backslash). Pour ce faire, vous devrez d'abord remplacer tous les doubles antislashs avec

string.replaceAll("\\\\\\\\", ESCAPE_BACKSLASH) 

(où ESCAPE_BACKSLASH est une chaîne qui ne se produira pas dans votre entrée) puis, après la séparation en utilisant l'affirmation de regarder en arrière, remplacer la chaîne de ESCAPE_BACKSLASH avec une barre oblique inverse avec séquence d'échappement

token.replaceAll(ESCAPE_BACKSLASH, "\\\\") 
0

Gumbo a droit à l'aide d'un look-behind assertion, mais dans le cas où votre chaîne contient le caractère d'échappement échappé (par exemple \\) juste en face d'une virgule, la scission pourrait se briser. Voir cet exemple:

test1\,test1,test2\\,test3\\\,test3\\\\,test4

Si vous faites simple scission regarder en arrière pour (?<!\\), comme suggéré Gumbo, la chaîne obtient divisée en deux parties seulement test1\,test1 et test2\\,test3\\\,test3\\\\,test4. C'est parce que le look-behind vérifie juste un caractère pour le caractère d'échappement. Ce qui serait réellement correct, si la chaîne est divisée par des virgules et des virgules précédées d'un nombre pair de caractères d'échappement.

Pour y parvenir il faut un coup d'oeil-derrière expression un peu plus complexe (double):

(?<!(?<![^\\]\\(?:\\{2}){0,10})\\),

En utilisant cette expression régulière plus complexe en Java, a encore besoin d'échapper à toute \ par \\. Donc, cela devrait être une réponse plus sophistiquée à votre question:

"any comma separated string".split("(?<!(?<![^\\\\]\\\\(?:\\\\{2}){0,10})\\\\),"); 

Note: Java ne supporte pas les répétitions infinies de l'intérieur d'assertions arrières. Par conséquent, seuls 10 caractères d'échappement doubles répétés sont vérifiés en utilisant l'expression {0,10}. Si nécessaire, vous pouvez augmenter cette valeur en ajustant le dernier nombre.

Questions connexes