replace exact match in php - php

im new to regular expressions in php.
I have some data in which some of the values are stored as zero(0).What i want to do is to replace them with '-'. I dont know which value will get zero as my database table gets updated daily thats why i have to place that replace thing on all the data.
$r_val=preg_replace('/(0)/','-',$r_val);
The code im using is replacing all the zeroes that it finds for eg. it is even replacing zero from 104.67,giving the output 1-4.56 which is wrong. i want that data where value is exact zero that must be replaced by '-' not every zero that it encounter.
Can anyone please help!!
Example of the values that $r_val is having :-
10.31,
391.05,
113393,
15.31,
1000 etc.

This depends alot on how your data is formatted inside $r_val, but a good place to start would be to try:
$r_val = preg_replace('/(?<!\.)\b0\b(?!\.)/', '-', $r_val);
Where \b is a 0-length character representing the start or end of a 'word'.
Strange as it may sound, but the Perl regex documentation is actually really good for explaining the regex part of the preg_* functions, since Perl is where the functionality is actually implemented.

Again, it would be more than helpful if you could supply an example of what the $r_val string really looks like.
Note that \b matches at word boundaries, which would also turn a string like "0.75" into "-.75". Not a desirable result, I guess.

Whilst the other answer does work, it seems overly complex to me. I think you need only to use the ^ and $ chars either side of 0.
$r_val = preg_replace('/^0+$/', '&#45', $r_val);
^ indicates the regex should match from the beginning of the line.
$ indicates the regex should match to the end of the line.
+ means match this pattern 1 or more times
I altered the minus sign to it's html code equivalent too. Paranoid, yes, but we are dealing with numbers after all, so I though throwing a raw minus sign in there might not be the best idea.

Why not just do this?
if ( $r_val == 0 )
$r_val = '-';
You do not need to use a regex for this. In fact, I'd advise against doing so for performance reasons. The operation above is approximately 20x faster than the regex solution.
Also, the PHP manual advises against using regexes for simple replacements:
If you don't need fancy replacing rules (like regular expressions), you should always use this function instead of ereg_replace() or preg_replace().
http://us.php.net/manual/en/function.str-replace.php
Hope that helps!

Related

Regex Multiple Matches PHP

I'm trying to get all numbers from a string, having - or _ before the number and optional - _ space or the end of string at the end of the number.
So, my regex looks like this:
[-_][\d]+[-_ $]?
My problem is, I don't match numbers right after each other. From a "foo-5234_2123_54-13-20" string, I only get 5234, 54 and 20.
What I tried is the following regexes: (?:[-_])[\d]+(?:[-_ $])? and [-_]([\d]+)[-_ $]? that obviously didn't work. I'm looking for hours now and I know it can't be that hard so I hope someone can help me here.
If that makes any difference, I'm using PHP preg_match_all.
You just need to use look-arounds:
(?<=[-_])\d+(?=[-_ ]|$)
See demo
Fortunately, PHP supports at least fixed-width look-behinds, and we can use it here.

Building a regex expression for PHP

I am stuck trying to create a regex that will allow for letters, numbers, and the following chars: _ - ! ? . ,
Here is what I have so far:
/^[-\'a-zA-Z0-9_!\?,.\s]+$/ //not escaping the ?
and this version too:
/^[-\'a-zA-Z0-9_!\?,.\s]+$/ //attempting to escape the ?
Neither of these seem to be able to match the following:
"Oh why, oh why is this regex not working! It's getting pretty frustrating? Frustrating - that is to say the least. Hey look, an underscore_ I wonder if it will match this time around?"
Can somebody point out what I am doing wrong? I must point out that my script takes the user input (the paragraph in quotes in this case) and strips all white space so actual input has no white space.
Thanks!
UPDATE:
Thanks to Lix's advice, this is what I have so far:
/^[-\'a-zA-Z0-9_!\?,\.\s]+$/
However, it's still not working??
UPDATE2
Ok, based on input this is what's happening.
User inputs string, then I run the string through following functions:
$comment = preg_replace('/\s+/', '',
htmlspecialchars(strip_tags(trim($user_comment_orig))));
So in the end, user input is just a long string of chars without any spaces. Then that string of chars is run using:
preg_match("#^[-_!?.,a-zA-Z0-9]+$#",$comment)
What could possibly be causing trouble here?
FINAL UPDATE:
Ended up using this regex:
"#[-'A-Z0-9_?!,.]+#i"
Thanks all! lol, ya'll are going to kill me once you find out where my mistake was!
Ok, so I had this piece of code:
if(!preg_match($pattern,$comment) || strlen($comment) < 2 || strlen($comment) > 60){
GEEZ!!! I never bothered to look at the strlen part of the code. Of course it was going to fail every time...I only allowed 60 chars!!!!
When in doubt, it's always safe to escape non alphanumeric characters in a class for matching, so the following is fine:
/^[\-\'a-zA-Z0-9\_\!\?\,\.\s]+$/
When run through a regular expression tester, this finds a match with your target just fine, so I would suggest you may have a problem elsewhere if that doesn't take care of everything.
I assume you're not including the quotes you used around the target when actually trying for a match? Since you didn't build double quote matching in...
Can somebody point out what I am doing wrong? I must point out that my script takes the user input (the paragraph in quotes in this case) and strips all white space so actual input has no white space.
in which case you don't need the \s if it's working correctly.
I got the following code to work as expected to (running php5):
<?php
$pattern = "#[-'A-Z0-9_?!,.\s]+#i";
$string = "Oh why, oh why is this regex not working! It's getting pretty frustrating? Frustrating - that is to say the least. Hey look, an underscore_ I wonder if it will match this time around?";
$results = array();
preg_match($pattern, $string, $results);
echo '<pre>';
print_r($results);
echo '</pre>';
?>
The output from print_r($results) was as following:
Array
(
[0] => Oh why, oh why is this regex not working! It's getting pretty frustrating? Frustrating - that is to say the least. Hey look, an underscore_ I wonder if it will match this time around?
)
Tested on http://writecodeonline.com/php/.
It's not necessary to escape most characters inside []. However, \s will not do what you want inside the expression. You have two options: either manually expand (/^[-\'a-zA-Z0-9_!?,. \t\n\r]+$/) or use alternation (/^(?:[-\'a-zA-Z0-9_!?,.]|\s)+$/).
Note that I left the \ before the ' because I'm assuming you're putting this in a PHP string and I wouldn't want to suggest a syntax error.
The only characters with a special meaning within a character class are:
the dash (since it can be used as a delimiter for ranges), except if it is used at the beginning (since in this case it is no part of any range),
the closing bracket,
the backslash.
In "pure regex parlance", your character class can be written as:
[-_!?.,a-zA-Z0-9\s]
Now, you need to escape whatever needs to be escaped according to your language and how strings are written. Given that this is PHP, you can take the above sample as is. Note that \s is interpreted in character classes as well, so this will match anything which is matched by \s outside of a character class.
While some manuals recommend using escapes for safety, knowing the general regex rules for character classes and applying them leads to shorter and easier to read results ;)

Parse block with php regex

I'm trying to write a (I think) pretty simple RegEx with PHP but it's not working.
Basically I have a block defined like this:
%%%%blockname%%%%
stuff goes here
%%%%/blockname%%%%
I'm not any good at RegEx, but this is what I tried:
preg_match_all('/^%%%%(.*?)%%%%(.*?)%%%%\/(.*?)%%%%$/i',$input,$matches);
It returns an array with 4 empty entries.
I guess it also, apart from actually working, needs some sort of pointer for the third match because it should be equal to the first one?
Please enlighten me :)
You need to allow the dot to match newlines, and to allow ^ and $ to match at the start and end of lines (not just the entire string):
preg_match_all('/^%%%%(.*?)%%%%(.*?)%%%%\/(.*?)%%%%$/sm',$input,$matches);
The s (single-line) option makes the dot match any character including newlines.
The m (multi-line) option allows ^ and $ to match at the start and end of lines.
The i option is unnecessary in your regex since there are no case-sensitive characters in it.
Then, to answer the second part of your question: If blockname is the same in both cases, then you can make that explicit by using a backreference to the first capturing group:
preg_match_all('/^%%%%(.*?)%%%%(.*?)%%%%\/\1%%%%$/sm',$input,$matches);
I'm pretty sure you can't since these operations would need to save a variable and you can't in regex. You should try to do this using PHP's built-in token parser. http://php.net/manual/en/function.token-get-all.php

how to do the regexp in javascript for this string?

I have the following possible string:
'', or '4.', or '*.4' or '4.35'
all the above format are valid, others are all invalid.
basically, if I don't care the digit or word character, this is what I used in PHP for the validation:
else if ( !ereg('^\*|.*\..*$',$bl_objver) )
Now, I would like to add some clientside validation, so I just translate it into javascript:
var ver_reg = new RegExp("^\*|.*\..*$");
if (ver_reg.test(obj_ver) == false)
but firebug always shows some error, like: "invalid quantifier |...*$" etc..
any suggestions?
(I'm not convinced your expression is correct, but for the moment just going with what you have.)
Using the RegExp object, you need to escape the slashes:
var ver_reg = new RegExp("^\\*|.*\\..*$");
Alternatively you can use regex literal notation:
var ver_reg = /^\*|.*\..*$/;
That answers your direct question, but...
As for the expression, well, what you definitely want to correct is the start/end anchors each applying to one side of the alternation.
i.e. you're saying <this>|<that> where <this> is ^\* and <that> is .*\..*$
What you want is ^(?:<this>|<that>)$ to ensure the start/end markers are not part of the alternatives (but using ?: since we're not capturing the group).
So /^(?:\*|.*\..*)$/ using the second example above - this fix would also need applying to the PHP version (which can use the same syntax).
I'd also question your use of . instead of \w or [^.] or similar, but without knowing what you're actually doing, I can't say for sure what makes most sense.
Hope this helps! :)

How can I match everything with a PHP regular expression?

How can I match everything with a PHP regular expression? I tried: /[.\r\n]*/, but it isn't working. Any ideas? Thanks.
This is for a method I made for a PHP class to parse e-mails:
public function getHeader($headerName) {
preg_match('/[\r\n]' . $headerName . '[:][ ](.+)[\r\n][^ \t]/Uis', "\n" . ltrim($this->originalMessage), $matches); return preg_replace('/[\r\n]*/', '', $matches[1]);
}
/.*/s (see perl's docs). The s option means (quoting from that URL):
Treat string as single line. (Make . match a newline)
I assume, based on your inclusion of \n and \r above, that you want to match across multiple lines. In this case, use:
/.*/s
(note the explicit /s modifier, that is, change . to match any character whatsoever, even a newline, which it normally would not match.)
See http://www.perl.com/doc/manual/html/pod/perlre.html
Why do you want to match everything? There's no point in using it as a condition because it's always true. If you want to capture the text you don't need a regex to do it because you just use the entire string. If you're trying to get around taint-checking, then shame on you (and ask a separate question about doing that right).
Note that we have a bit of the XY Problem here. You have some task X in mind, and think Y is part of the solution. You ask about Y but never tell us X. It's hard to answer your real question when we don't know what you are trying to do. :)
What about /.*/s?
In a character class ( the [] ), . just means period.
Does /[\.\r\n]+/ do what you want?
This kludge has also worked for me before:
my $abstract_text = /Abstract:([\s\S]+?)\nReferences/m;
It's useful if you want to capture patterns with arbitrary text included or intervening between multiple captures.

Categories