View Full Version : Replace only A-Z/0-9 using ereg_replace();
JShor
06-18-2010, 06:35 AM
I'm using a PHP version earlier than 5.3.0.
I have a series of stock numbers on a page, that I need to detect and replace. The pattern of each stock number are letters and numbers, containing a period somewhere in between, and possibly a dash.
The code I have works to detect the stock numbers, however they include the HTML tags if they are not separated by a space.
$text = "<strong>34D-23.48</strong>";
$text = ereg_replace("([a-zA-Z0-9]+.+[a-zA-Z0-9])",
"Stock # \\0", $text);
echo $text;
However, the resulting HTML outputs as this:
<Stock #strong>34D-23.48</strong>
I can't separate the stock numbers, how do I get it so the output is like this?
<strong>Stock #34D-23.48</strong>
Thanks in advance for the help. :]
-Josh
james438
06-18-2010, 07:25 AM
Honestly, I am quite rusty when it comes to ereg_replace(). I am having some trouble remembering the syntax for ereg, which does differ somewhat from PCRE. ereg_replace() is the more processor heavy version of preg_replace() and has since been deprecated. I was thinking that it had been removed completely in more recent versions of php, but I have not found any reference to back that up, so I am probably mistaken there.
I'm sure you could do the same thing with preg_replace
<?php
$text = "<strong>34D-23.48</strong>";
$text = preg_replace("/>\s?([\w.\-]{1,})\s?</", ">Stock # $1<", $text);
echo $text;
?>\s? is for optional whitespace. \w is a word character, which is A-Za-z0-9 and the underscore. \- is for the dash, but since it is in a character class it needs to be escaped. the dot does not need to be escaped if it is within a character class. {1,} is a quantifier saying that there must be one or more of the character class.
If you really want it in ereg_replace format, let me know and I'll see what I can come up with.
The above script assumes that the stock number is between > and <.
JShor
06-18-2010, 12:35 PM
Yes, preg_replace() accomplishes the same thing. Thanks a million James, the code worked. :]
akitodito
06-18-2010, 01:10 PM
Yes preg_replace() is a much better option if only purely based on speed. It depends how much it's called but i had a loop processing a lot of data and i timed both ereg and preg.. preg was faster by quite a few seconds!
JShor
06-18-2010, 03:51 PM
Alright, that issue is solved, but I have one more minor problem. I have numbers which display as a period at the beginning or end of a set of characters. I want to exclude these from being replaced.
For example, I will have .093 or 093., which are not supposed to be replaced. Can you modify the code so that it only replaces stock #'s with periods in the middle?
Also, the majority of the stock #'s have a </td> tag right after the number. When I tried modifying the code to include that in the replacement, it gives me an error.
This is the code;
$text = preg_replace("/>\s?([\w.\-]{1,})\s?</" + "</td>", ">Stock # $1<", $text);
Help is greatly appreciated. :]
JShor
06-18-2010, 08:49 PM
Alright, I managed to figure it out. Thanks guys.
james438
06-18-2010, 08:56 PM
I am having a difficult time with this one. What was the solution?
james438
06-18-2010, 10:25 PM
k, I got it.
<?php
$text = "<strong>34D-23.48</strong>";
$text=preg_replace('/>\s?([\w\-]{1,}\.?)(?=((?!<\/?strong\b|>|\.\s?<).)*<\/strong)/','>stock # $1',$text);
echo "$text";
?>
JShor
06-19-2010, 02:31 AM
Still doesn't work. It will replace the stock number, but it also replaces ALL the strings which precede the </strong> tag. I'm stumped. :confused:
When I have this code:
$text = "<strong>DontReplaceThis</strong>";
I get this result:
stock # DontReplaceThis
It's not replacing JUST the string pattern with the decimal place.
Once again, help is greatly appreciated. Thank you. :]
james438
06-19-2010, 02:48 AM
That is what it is supposed to do.
Could you give some examples of what you want replaced and what you do not want replaced? The only thing I can think of is that I have not yet restricted it to match the string that is between the <strong> tags that also contains a dot in the middle somewhere.
Basically it looks for all data between <strong> tags where the string is not preceded or appended with a dot. The string must begin with a letter or a number or underscore or dash and end with the same. periods can be in the middle of the string, but the period is optional.
JShor
06-19-2010, 03:09 AM
Basically it looks for all data between <strong> tags where the string is not preceded or appended with a dot. The string must begin with a letter or a number or underscore or dash and end with the same. periods can be in the middle of the string, but the period is optional.
All of that statement is correct, except the period is not optional. I want only stock numbers replaced, and only stock numbers have a period. Therefore, the period is mandatory.
james438
06-19-2010, 05:01 AM
Easy enough to fix:
<?php
$text = "<strong>34D-2348</strong>";
$text=preg_replace('/>\s?([\w\-]{1,}\.[\w\-]{1,})(?=((?!<\/?strong\b|>|\.\s?<).)*<\/strong)/','>stock # $1',$text);
echo "$text";
?>
Sorry, I think I was just being lazy. Be sure to test it out to see if there are any glitches I may have missed.
Here is some small explanation of the PCRE tools I used.
? listed after a character type or match makes the preceding match optional.
{1,} this means 1 or more.
$1 is the first subpattern captured. subpatterns are numbered starting from the first opening parentheses from left to right with $0 as the entire pattern.
?= listed just inside a parentheses means that the following must come after what was listed previously. This is known as an assertion. Assertions are also a bit more complicated and do not follow the same rules as the Perl regular expression engine. This is one of the few differences from Perl regular expressions. Assertions can be nested, but the assertion cannot be repeated, for example I can't say '/p(?=p)*/' (?= is known as a lookahead. You can't have a lookahead and a lookbehind with PCRE, which is what made the regex a little tricky to create.
Assertions is another way of saying "this MUST follow that" or "this MUST NOT follow that" or "this MUST precede that". Again, assertions can be nested as demonstrated above.
You can read up more on assertions here (http://us.php.net/manual/en/regexp.reference.assertions.php), but I find the PHP manual of PCRE somewhat lacking and even more so now that all of the hundreds of very useful comments were removed.
JShor
06-19-2010, 11:58 AM
I figured it all out, but there is one last problem. If I put quotes around $1, it doesn't encase the entire stock number, only the first part before the decimal place. Here is the code:
$text = preg_replace('/>\s?([\w\-]{1,}\.)/','>stock # "$1" ',$text);
Instead of getting stock # "34D-23.48", I get: stock # "34D-23."48.
james438
06-19-2010, 12:16 PM
With the script you are using you are only capturing up to the period with the exceptions we already discussed: it can't begin or end with a period and must have a period in the middle, it may or may not begin and/or end with a space, it is all wrapped in <strong> tags.
With the one I posted you will capture everything between the <strong> tags and not just everything up to the period.
JShor
06-19-2010, 03:20 PM
Right, I used the code you last posted, works perfectly. It replaces all the stock numbers with containers (which is what I originally had intended). I really need to get used to using preg_replace() now that ereg_replace() is deprecated in the latest PHP versions. Thanks again. :]
james438
06-20-2010, 01:30 AM
I am not sure of all the ins and outs of what you need the script for, but the following is better than what I posted earlier and easier to understand.
<?php
$text = "<strong>34D-2.348</strong>";
$text = preg_replace('/strong>\s?([\w\-]{1,}\.[\w\-]{1,})(?!\.)\s?<\/strong/','strong>stock # $1</strong',$text);
echo "$text";
?>
Well, maybe not better, but I find it easier to understand. They both do pretty much the same thing, but this one is somewhat stricter about being between <strong> tags.
Powered by vBulletin® Version 4.2.2 Copyright © 2021 vBulletin Solutions, Inc. All rights reserved.