views:

64

answers:

3

I want to enforce single question mark at the and of the string. In JavaScript it works perfectly:

var re = /[?7!1]*$/;
document.write('lolwut'.replace(re, '?'));
document.write('lolwut?'.replace(re, '?'));
document.write('lolwut??'.replace(re, '?'));
document.write('lolwut???'.replace(re, '?'));
document.write('lolwut???!!!11'.replace(re, '?'));

All of returned values equals "lolwut?" PHP variant doesnt work that smooth:

$re = '/[?7!1]*$/';
echo preg_replace($re, '?', 'lolwut') . "\n";
echo preg_replace($re, '?', 'lolwut?') . "\n";
echo preg_replace($re, '?', 'lolwut??') . "\n";
echo preg_replace($re, '?', 'lolwut???') . "\n";
echo preg_replace($re, '?', 'lolwut???!!!11') . "\n";

output is:

lolwut?
lolwut??
lolwut??
lolwut??
lolwut??

What i'm doing wrong here?


Update:

$ (Dollar) Assert end of string
An assertion is a test on the characters following or preceding the current matching point that does not actually consume any characters.

is my confusion here, along with implicit global flag of preg_replace, thanks to salathe for providing a clue. (you guys should vote his answer up, really)

+2  A: 

You should use the trim function:

echo trim('lolwut???!!!11', '?7!1');

output is:

lolwut
SirDarius
rtrim would be more appropriate, but +1 for a viable solution.
Andy E
yes my bad, I also forgot to add '?' at the end.
SirDarius
+8  A: 

Checkout rtrim() - http://php.net/manual/en/function.rtrim.php

echo rtrim('lolwut','?7!1').'?'; // lolwut?
echo rtrim('lolwut?','?7!1').'?'; // lolwut?
echo rtrim('lolwut??','?7!1').'?'; // lolwut?
echo rtrim('lolwut???!!!11','?7!1').'?'; // lolwut?
echo rtrim('lolwut1??!7!11','?7!1').'?'; // lolwut?

rtrim will Strip whitespace (or other characters) from the end of a string

The second argument:

You can also specify the characters you want to strip, by means of the charlist parameter. Simply list all characters that you want to be stripped. With .. you can specify a range of characters.

Lizard
+1, a much better solution.
Andy E
+3  A: 

Just to answer the question asked ("What i'm doing wrong here?"), you're being confused about what precisely the regular expression matches. With the strings presented, bar the first one, the regex actually matches twice which is why you get two question marks (two matches, two replacements). The root of this behaviour is a mixture of the quantifier (* allows matching nothing) and the end-anchor ($ matches the end of the string).

For lolwut???!!!11:

  • The regex first matches ???!!!11 which is what you expect
  • Giving the string a new value of lulwut?
  • Then it also matches at the point right at the end of the new string
  • Leading to a final replaced value of lulwut??

If you wanted to continue using the same regex with preg_replace then simply restrict it to one replacement by providing a value of 1 to the fourth ($limit) argument:

preg_replace('/[?7!1]*$/', '?', 'lolwut???!!!111', 1);
// limit to only one replacement ------------------^ 

As for a better solution, as the others have said, use rtrim.

salathe