3

Comments below showed me that there was a functionality bug in my code. The question was updated to match.

So I have a regex that finds bb style quote and replaces them with a blockquote.

$text = preg_replace("/\[quote(?:=\"(\w+?)\")?]/", '<blockquote class="quote"><div class="quotee">\1 says:</div>', $text);
$text = preg_replace("/\[\/quote\]/m", '</blockquote>', $text);

It works just fine (its in a while loop to get recursive quotes), but later on, I use nl2br. However, I don't want to add a br after the blockquote, so I want to remove the newline right after the pattern, but nothing I've done has worked.

I've tried:

/\[\/quote\][\r\n]?/ms
/\[\/quote\][\r\n]*/ms
/\[\/quote\][\r\n]{0,2}/ms
/\[\/quote\](?:[\r\n]|\r\n)?/ms

Any advice?

Rohit
  • 3,018
  • 2
  • 29
  • 58
  • Your first (and the others) are wrong. Need info: Does the string contain multiple bb codes? Are they nested (don't know bb details)? Do they span lines? –  Nov 27 '13 at 16:47
  • Yes, it can contain multiple codes, and quotes can be nested. They do span lines. You're saying the first one is wrong, yet it works perfectly in application? – Rohit Nov 27 '13 at 16:51
  • Need example of nested double quotes. Ie `"asdf'asdf"` is ok, `"this is " quote"` might be problamatic. –  Nov 27 '13 at 16:53
  • When I said nested quotes, I meant the nested quote tags, not nested quote punctuation. I'm confused why quote punctuation matters, save for inside the opening quote bb tag? – Rohit Nov 27 '13 at 16:57
  • Ok, so nested bb Quote tags. Requires recursion regex. The `.*` in your regex will find everything from the first opening quote to the last closing quote. It is a fluke if its working for you. –  Nov 27 '13 at 17:05
  • I can make such a regex but without source examples I can't test it. If what you have is working, try adding `[^\S\r\n]*[\r\n]*` to the end of it. –  Nov 27 '13 at 17:08
  • Ah, I found a situation that didn't work; two quotes on the same post. I'm not sure if that's what you meant, but I've fixed the code to work and updated the question to match. – Rohit Nov 27 '13 at 17:40
  • As an additional note, I tried `\[\/quote\][\r\n]*` in a regex tool (like in an answer below), and it works, but when I try it in the PHP, it doesn't... – Rohit Nov 27 '13 at 17:49
  • I don't know what the problem is but you should remove the //`ms` modifiers in your regexes. They have no affect whatsoever in your current regex list. `m` turns `^$` into line begin/end. `s` makes the `.` dot metachar match everything (including \r\n). And if you use `\s*+` at the end it should possesively match any whitespace (including linebreaks) at the end. If thats not working, the problem lies elsewhere. –  Nov 27 '13 at 17:59
  • would you update your answer with a live example from regex101.com or the like? – revo Nov 27 '13 at 19:00

2 Answers2

1

Try using a tool like this one, worked wonders for me :)

http://gskinner.com/RegExr/

runelynx
  • 403
  • 2
  • 4
  • 17
  • 2
    This seems more like a comment than an answer. – Barmar Nov 27 '13 at 16:33
  • Oh... It wont let me comment up above, just wanted to share what helped me with regex :/ – runelynx Nov 27 '13 at 16:35
  • 1
    @runelynx You need 50 reputation to comment on other people's answers/questions. You just need one more upvoted answer to get there. – zsaat14 Nov 27 '13 at 16:42
  • I've used a number of tools; as you can see, I have some examples of what I've tried. I can't seem to figure out what the correct regex would be. Some stuff is working in test tools like that, but not in my actual code. – Rohit Nov 27 '13 at 16:48
1

Try this. Don't use /../sm any modifiers (s is included in the regex)
Edit - added trailing whitespace expression

 #  '/(?s)\[quote(?:="(.*?)")?\](.*?)\[\/quote\][^\S\r\n]*[\r\n]*/'


 (?s)
 \[quote
 (?:
      =
      "
      ( .*? )        # (1)
      "
 )?
 \]
 ( .*? )             # (2)
 \[\/quote\]
 [^\S\r\n]* 
 [\r\n]* 
  • Sorry, not sure I know what the (?s) at the beginning is supposed to do? And this works on regex testers, but not when I plug it into PHP. – Rohit Nov 27 '13 at 17:54
  • @RhoVisions - This construct `(?letters)` is called a modifier group. Most of the options here `/../here` are modifiers available that can be inserted inline into the regex expresion. I added `(?s) ` because the 'Dot-All' modifier is needed with the `( .*? )` sub-expression in my regex. Since there are no ^$ anchors anywhere, the `/../m` modifier is not needed as well. So, no modifiers are needed in this form `/../none`. It sounds like you are not `quoting` properly in the PHP code. Try this `"/(?s)\\[quote(?:=\"(.*?)\")?\\](.*?)\\[\\/quote\\][^\\S\\r\\n]*[\\r\\n]*/" ` –  Nov 27 '13 at 21:12