2010-09-27 8 views
0

Je suis en train de mettre à jour un programme qui corrige des sous-titres. Jusqu'à présent, je m'en suis sorti sans utiliser d'expressions régulières, mais le dernier problème qui s'est présenté pourrait bénéficier de leur utilisation. (Je l'ai déjà résolu sans expressions régulières, mais c'est une méthode très peu optimisée qui ralentit considérablement mon programme).Problème complexe. Besoin d'aide avec l'expression régulière remplacer

TL; DR;

Je suis en train de faire les travaux suivants:

Je veux que tous les cas de:
"! .", "!." et "! . " à devenir: "!"

à moins que le point est suivi d'un autre point, dans lequel cas je veux tous les cas de:
"!..", "! ..", "! . . " et "!. ." à devenir: "!..."

J'ai essayé ce code:

the_str = Regex.Replace(the_str, "\\! \\. [^.]", "\\! [^.]"); 

qui se rapproche de la première partie de ce que je veux faire, mais je ne peux pas faire le caractère [^.] de la chaîne de remplacement être le même caractère que le un dans la chaîne originale ... S'il vous plaît, aidez!

Je suis intéressé par les deux C implémentations # et PHP ...

Répondre

1
$str = preg_replace('/!(?:\s*\.){2,3}/', '!...', $str); 
$str = preg_replace('/!\s*\.(?!\s*\.)/', '!', $str); 

Cela fait le travail pour PCREs. Vous pourriez probablement faire un peu de magie pour le fusionner à un, mais ce ne serait plus lisible. Le premier PCRE est pour !..., le second pour !. Ils sont assez simples.

+0

Votre deuxième 'preg_replace' ne correspondra-t-il pas aux remplacements effectués dans le premier? - Ça ne fait rien. Je vois pourquoi ça ne va pas maintenant. – BBonifield

+0

déjà fixé que;) mais oui, la première version serait. – NikiC

+0

Merci, ça a marché comme un charme! – funkybomber

0

C#

s = Regex.Replace(s, @"!\s?\.\s?(\.?)\s?", "!$1$1$1"); 

PHP

$s = preg_replace('/!\s?\.\s?(\.?)\s?/', '!$1$1$1', $s); 

Le premier point est consommé mais pas capturé; vous jetez effectivement celui-là. Le groupe # 1 capture le second point s'il y en a un, ou une chaîne vide sinon. Dans les deux cas, le brancher trois fois dans la chaîne de remplacement donne le résultat souhaité.

J'ai utilisé \s à la place des espaces littéraux pour rendre plus évident ce que je faisais, et j'ai ajouté le quantificateur ? pour rendre les espaces optionnels. Si vous avez vraiment besoin de le restreindre aux caractères d'espace réels (pas les onglets, les retours à la ligne, etc.), vous pouvez les changer en espaces. Si vous souhaitez autoriser plus d'un espace à la fois, vous pouvez changer ?-* le cas échéant - par exemple .:

@"!\s*\.\s*(\.?)\s*" 

En outre, notez l'utilisation de chaînes in extenso de C# littéraux - l'antidote pour backslashitis. ;)

Questions connexes