2010-02-08 21 views
3

Je fais un simple analyseur Textile et j'essaie d'écrire une expression régulière pour "blockquote" mais j'ai de la difficulté à faire correspondre plusieurs nouvelles lignes. Exemple:Expression régulière pour faire correspondre un bloc de texte à la première double nouvelle ligne?

 
bq. first line of quote 
second line of quote 
third line of quote 

not part of the quote 

Il sera remplacé par des balises blockquote via preg_replace() donc en gros, il doit correspondre à tout entre "bq." et le premier double nouvelle ligne qu'il rencontre. Le mieux que je peux gérer est d'obtenir la première ligne de la citation. Merci

+0

Par "simple" voulez-vous dire que vous soutenez un très petit sous-ensemble de balisage Textile? Sinon, je vous suggère de reconsidérer en utilisant 'preg_replace()'; vous trouverez bientôt que cela rend le travail * plus * difficile, pas moins. Vous ferez probablement mieux de ne pas utiliser d'expressions rationnelles. –

+0

Oui, ce n'est qu'une petite partie du balisage que je supporte. Par intérêt, comment le feriez-vous sans utiliser des regex? Aurais-je pensé que vous deviez les utiliser à un moment donné (même si vous utilisez un preg_match) pour savoir quel balisage est utilisé? – Fourjays

Répondre

6

Essayez cette regex:

(?s)bq\.((?!(\r?\n){2}).)*+ 

sens:

(?s)   # enable dot-all option 
b    # match the character 'b' 
q    # match the character 'q' 
\.    # match the character '.' 
(    # start capture group 1 
    (?!   # start negative look ahead 
    (   #  start capture group 2 
     \r?  #  match the character '\r' and match it once or none at all 
     \n  #  match the character '\n' 
    ){2}  #  end capture group 2 and repeat it exactly 2 times 
)   # end negative look ahead 
    .   # match any character 
)*+   # end capture group 1 and repeat it zero or more times, possessively 

Le \r?\n correspond à un ordinateur Windows, * nix et (les plus récents) les sauts de ligne MacOS. Si vous devez comptabiliser de vrais anciens ordinateurs Mac, ajoutez le \r: \r?\n|\r

+1

J'utiliserais probablement '{2}' à la place de '{2,}' parce que vous ne pouvez pas dire si manger toutes les nouvelles lignes adjacentes est souhaitable. Cela ne fait certainement pas partie de l'exigence. – Tomalak

+0

+1, très bien. Pourquoi le quantificateur possessif, cependant, si rien d'autre ne suit le groupe de capture? –

+0

@Tomalak: accepté. Fixé. –

0

Est-ce que cela fonctionnerait?

'/(.+)\n\n/s' 

Je crois que 's' représente une ligne simple.

+0

's' est généralement appelé 'dot-all' (car il laissera également le' .' correspondre aux sauts de ligne). Mais en faisant ce que vous suggérez, la regex va correspondre à tout le texte, et retournera dans la chaîne pour trouver le dernier \ n \ n. À partir de la chaîne 'ABC \ n \ nDEF \ n \ nGHIJ \ n \ nKLM', elle correspond' ABC \ n \ nDEF \ n \ nGHIJ \ n \ n'. Pas ce que les Fourjays recherchent pour l'OMI. –

+0

C'est vrai. Devrait faire + non-faim, je suppose .. Merci. – ziya

0

Mon instinct me dit quelque chose comme ...

preg_match("/^bq\. (.+?)\n\n/s", $input, $matches) 

Tout comme le dit ci-dessus Fella, le drapeau s après la / à la fin du RegEx signifie que le . correspondront caractères de nouvelle ligne. Habituellement, sans cela, les RegEx sont une sorte de chose d'une ligne.

Ensuite, le point d'interrogation ? après le .+ indique une correspondance non gourmande pour que le .+ ne corresponde pas comme il le peut; à la place, il correspondra au minimum possible, de sorte que le \n\n correspondra à la première ligne double disponible. Dans quelle mesure comptez-vous prendre en charge les fonctionnalités de Textile? Parce que votre RegEx peut être assez compliqué, comme textile permet des choses comme ...

bq.. This is a block quote 

This is still a block quote 

ou ...

bq(funky). This is a block quote belonging to the class funky! 

bq{color:red;}. Block quote with red text! 

Toutes dont votre technique regex remplacer ne sera pas en mesure de gérer, il me semble

+0

Je ne supporte que ce que je considère comme les caractéristiques les plus communes (gras, italique, barré, guillemets, titres, paragraphes, puces). Serait seulement utiliser les classes sur le paragraphe tout au plus. Jusqu'à présent, la regex fonctionne bien pour des choses comme le gras, mais je suppose que je vais devoir faire quelque chose de plus impliqué pour la liste à puces. – Fourjays

+0

... et imbriqué gras/italique? Je pense que '* ceci ne fonctionnera pas avec RegEx *' –

+0

Les caractères gras/italiques imbriqués semblent fonctionner correctement. En utilisant l'expression rationnelle, elle remplace directement le contenu de la "balise" en gras, de sorte que les italiques restent intacts. – Fourjays

0

Edit: Ehr, mal lu la question .. "bq." était significatif.

echo preg_replace('/^bq\.(.+?)\n\n/s', '<blockquote>$1</blockquote>', $str, 1); 

Parfois, des données entrées par webforms contient \ r \ n au lieu de simplement \ n ce qui rendrait

echo preg_replace('/^bq\.(.+?)\r\n\r\n/s', '<blockquote>$1</blockquote>', $str, 1); 

Le questionmark fait ajouter les blocs de citation de fermeture après le premier retour à double trouvé ("non gourmand" je crois que ça s'appelle), donc tous les autres retours doubles sont laissés seuls (si ce n'est pas ce que vous voulez, enlevez-le évidemment).

1

Cette réponse acceptée n'a capturé que le dernier caractère du bloc pour moi.J'ai fini par utiliser ceci:

$text =~ /(?s)bq\.(.+?)\n\n/g