A couple of PHP ereg_replace questions. I have an array of names:
$ssKeywords = array("Str", "Int", "String", "As", "Integer", "Variant");
However when I use this ereg_replace:
foreach($arKeyword as $aWord) {
$sCode = ereg_replace($aWord, "<span class='ssKeyword'>".$aWord."</span>", $sCode);
}
It will only find the "str" or "int" not the full match. Apparently ereg_replace is greedy, so why is it not looking for the full match?
I managed to get comments working using preg_replace.
Do you need to use ereg? it has been deprecated and will be obsolete as of PHP 6. I suggest you use preg, which is also more efficient.
This information is available at php.net/ereg
Instead of searching for one term at a time better search for all of them at a time:
$sCode = preg_replace('/(?:'.implode('|', array_map('preg_quote', $ssKeywords)).')/', '<span class="ssKeyword">$0</span>', $sCode);
And if you sort the terms by its length, you will find Integer instead of just Int:
usort($ssKeywords, create_function('$a,$b', 'return strlen($b)-strlen($a);'));
Your problem is nothing to do with ereg_replace. Not only is preg_replace a better bet, but in fact in your case you aren't using any type of regular expressions; you're just doing a plain string match. So str_replace would be quicker and clearer.
The problem is that you're doing:
foreach($arKeyword as $aWord) {
which loops from the first to the last element of the array, testing the whole string against each of the keywords in the order you declared them. You declared ‘Int’ first, so any ‘Integer’ in the string will get replaced by “<span class="ssKeyword">Int</span>eger” before the loop gets as far as the ‘Integer’ keyword. By which time, with the “</span>” in the way, it'll never match.
Change the array order so that the longer keywords come first and it'll work.
If you're doing a plain-text match then str_replace is more efficient and less unnecessary. If you do need regular expressions any time in the future, use the preg_* functions because ereg_* is deprecated and preg_* is faster.
With regard to your question about "greedy", that refers to when you're actually using regular expressions. For example if you have the text:
Hello World! Hello World!
And use a regex like this:
/Hell(.+)rld!/
Then it will match the entire string because the + operator is greedy and finds as much as it can on one line. You'd need to do this to stop it being greedy and match each of the phrases:
/Hell(.+?)rld!/
Related
How to make one pattern string for preg_match_all() function If I have multiple strings to match like "G,C,D" & "A,B,C" & "E,C,D"
Currently my string is
$str = "/(?<=\b)([CDEFGAB](?:b|bb|m)*(?:#|##|sus|maj|min|aug)*[\d\/]*(?:[CDEFGAB](?:b|bb|m)*(?:#|##|sus|maj|min|aug)*[\d\/]*)*)(?=\s|$|(<.*>))(?! \w)/"
preg_match_all($str,$lyrics , $output_array);
I want to add these combinations ("G,C,D" & "A,B,C" & "E,C,D") in $str string.
NOTE this answer has been dramatically edited over time to arrive at this final conclusion.
by referring to this site: http://www.all-guitar-chords.com/ i came up with this regular expression:
\b(?:G,C,D|A,B,C|E,C,D)|(?:[ABCDEFG](?:#|b)?)(?:\/[ABCDEFG]b)?(?:(?:(?:maj|min|sus|add|aug|dim)(?:\d{0,2}(?:#\d{1,2}|sus\d)?)?)|(?:m\d{0,2}(?:(?:maj|add|#)\d{0,2})?)|(?:-?\d{0,2}(?:\([^)]*\)|#\d{1,2})?))?)
<?php preg_match_all( '`' . $reg_exp . '`', $str, $matches ); ?>
my final expression does NOT capture any backreferences. therefore, $matches[0] will be an array of the matches (because the zero-index array is always an array of the full strings that matched the full expression and subsequent arrays will refer to backreferences, if any).
it was written with as much precision as possible, but this expression could still return false positives, although very unlikely.
the only other way to do this is to use an array of each of the possible chords you are interested in. then iterate that array searching for each string explicitly -- and that would still be prone to false positives.
here is a site to tinker with it: https://regex101.com/r/vW9sJ2/7
NOTE the original question by the OP was how to add certain string combinations into the expression such as "G,C,D" or "A,B,C" (examples given by the OP). however, the musicians i spoke with said they couldn't see how extracting the chord combinations would be helpful as there are so many variations. they weren't even sure how extracting chords like this would help at all. which makes me curious as to what the OP intends to use this for and i hope he can explain for me (especially seeing how much time i spent on this given my obsessesive nature, lol).
EDIT without reply from the OP, not sure if this fulfills the OPs needs, and i've begun to wonder if he needs a more flexible match for the combinations (ex: G,C,D). so i've modified the expression to handle that:
\b(?:[ABCDEFG],[ABCDEFG],[ABCDEFG])\b|(?:[ABCDEFG](?:#|b)?)(?:\/[ABCDEFG]b)?(?:(?:(?:maj|min|sus|add|aug|dim)(?:\d{0,2}(?:#\d{1,2}|sus\d)?)?)|(?:m\d{0,2}(?:(?:maj|add|#)\d{0,2})?)|(?:-?\d{0,2}(?:\([^)]*\)|#\d{1,2})?))?)
and the fiddle for that: https://regex101.com/r/vW9sJ2/7
Here is a way to match your G,C,D-like strings:
\b
(?:(?:[CDEFGAB]
(?:b|bb|m)*
(?:\#|\#\#|sus|maj|min|aug)*
[\d\/]*
(?:[CDEFGAB]
(?:b|bb|m)*
(?:\#|\#\#|sus|maj|min|aug)*
[\d\/]*
)*
),?)+
(?=\s|$|(?:<.*>))
(?![[:blank:]]\w)
Or as a one-liner:
\b(?:(?:[CDEFGAB](?:b|bb|m)*(?:\#|\#\#|sus|maj|min|aug)*[\d\/]*(?:[CDEFGAB](?:b|bb|m)*(?:\#|\#\#|sus|maj|min|aug)*[\d\/]*)*),?)+(?=\s|$|(?:<.*>))(?![[:blank:]]\w)
I am looking for a way to replace all string looking alike in entire page with their defined values
Please do not recommend me other methods of including language constants.
Strings like this :
[_HOME]
[_NEWS]
all of them are looking the same in [_*] part
Now the big issue is how to scan a HTML page and to replace the defined values .
One ways to parse the html page is to use DOMDocument and then pre_replace() it
but my main problem is writing a pattern for the replacement
$pattern = "/[_i]/";
$replacement= custom_lang("/i/");
$doc = new DOMDocument();
$htmlPage = $doc->loadHTML($html);
preg_replace($pattern, $replacement, $htmlPage);
In RegEx, [] are operators, so if you use them you need to escape them.
Other problem with your expression is _* which will match Zero or more _. You need to replace it with some meaningful match, Like, _.* which will match _ and any other characters after that. SO your full expression becomes,
/\[_.*?\]/
Hey, why an ?, you might be tempted to ask: The reason being that it performs a non-greedy match. Like,
[_foo] [_bar] is the query string then a greedy match shall return one match and give you the whole of it because your expression is fully valid for the string but a non-greedy match will get you two seperate matches. (More information)
You might be better-off in being more constrictive, by having an _ followed by Capital letters. Like,
/\[_[A-Z]+\]/
Update: Using the matched strings and replacing them. To do so we use the concept called back-refrencing.
Consider modifying the above expression, enclosing the string in parentheses, like, /\[_([A-Z]+)\]/
Now in preg-replace arguments we can use the expression in parentheses by back-referencing them with $1. So what you can use is,
preg_replce("/\[_([A-Z]+)\]/e", "my_wonderful_replacer('$1')", $html);
Note: We needed the e modifier to treat the second parameter as PHP code. (More information)
If you know the full keyword you are trying to replace (e.g. [_HOME]), then you can just use str_replace() to replace all instances.
No need to make things like this more complex by introducing regex.
In PHP is there an equivalent to preg_match that does not require the use of regex? There is str_replace() for preg_replace. Is there something for preg_match.
*update * I am only looking to replace a known string with another. Using regex just seems like overkill.
I have the string "This is a [test1], and not a [test2]" and I want to match them with "[test1]" and "[test2]".
If you mean find a string within another string without using regex, you can use strpos
if (strpos('hello today', 'hello') !== false) {
// string found
}
Since I am not sure what result you are looking for I can't say if this is exactly what you are looking for.
You can use strpos to see if an occurrence of one string is in another.
To answer your question there is some function of PHP without regex
Do not use preg_match() if you only
want to check if one string is
contained in another string. Use
strpos() or strstr() instead as they
will be faster.
But they can not replace preg_match completely at all
First, str_replace() is not replacement for preg_replace(). Function str_replace() replaces all occurrences of the search string with the replacement string, preg_replace() replaces content selected by regular expressions (that's not same thing).
A lot of things require regex (and that's good) so you can't simply replace it with single PHP function.
Most developers use preg_match because they want to use the matches (the third parameter which will get set by the function).
I can not think of a function that will return or set the same information, as done with matches.
If however, you are using preg_match without regex then you might not care as much about the matches.
If you are using preg_match to see if there is a "match" and just that then I'd suggest using strpos instead, since it is much more efficient at seeing if one string is found in another.
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+$/', '-', $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!
It's been several years since I have used regular expressions, and I was hoping I could get some help on something I'm working on. You know how google's search is quite powerful and will take stuff inside quotes as a literal phrase and things with a minus sign in front of them as not included.
Example: "this is literal" -donotfindme site:examplesite.com
This example would search for the phrase "this is literal" in sites that don't include the word donotfindme on the webiste examplesite.com.
Obviously I'm not looking for something as complex as Google I just wanted to reference where my project is heading.
Anyway, I first wanted to start with the basics which is the literal phrases inside quotes. With the help of another question on this site I was able to do the following:
(this is php)
$search = 'hello "this" is regular expressions';
$pattern = '/".*"/';
$regex = preg_match($pattern, $search, $matches);
print_r($matches);
But this outputs "this" instead of the desired this, and doesn't work at all for multiple phrases in quotes. Could someone lead me in the right direction?
I don't necessarily need code even a real nice place with tutorials would probably do the job.
Thanks!
Well, for this example at least, if you want to match only the text inside the quotes you'll need to use a capturing group. Write it like this:
$pattern = '/"(.*)"/';
and then $matches will be an array of length 2 that contains the text between the quotes in element 1. (It'll still contain the full text matched in element 0) In general, you can have more than one set of these parentheses; they're numbered from the left starting at 1, and there will be a corresponding element in $matches for the text that each group matched. Example:
$pattern = '/"([a-z]+) ([a-z]+) (.*)"/';
will select all quoted strings which have two lowercase words separated by a single space, followed by anything. Then $matches[1] will be the first word, $matches[2] the second word, and $matches[3] the "anything".
For finding multiple phrases, you'll need to pick out one at a time with preg_match(). There's an optional "offset" parameter you can pass, which indicates where in the string it should start searching, and to find multiple matches you should give the position right after the previous match as the offset. See the documentation for details.
You could also try searching Google for "regular expression tutorial" or something like that, there are plenty of good ones out there.
Sorry, but my php is a bit rusty, but this code will probably do what you request:
$search = 'hello "this" is regular expressions';
$pattern = '/"(.*)"/';
$regex = preg_match($pattern, $search, $matches);
print_r($matches[1]);
$matches1 will contain the 1st captured subexpression; $matches or $matches[0] contains the full matched patterns.
See preg_match in the PHP documentation for specifics about subexpressions.
I'm not quite sure what you mean by "multiple phrases in quotes", but if you're trying to match balanced quotes, it's a bit more involved and tricky to understand. I'd pick up a reference manual. I highly recommend Mastering Regular Expressions, by Jeffrey E. F. Friedl. It is, by far, the best aid to understanding and using regular expressions. It's also an excellent reference.
Here is the complete answer for all the sort of search terms (literal, minus, quotes,..) WITH replacements . (For google visitors at the least).
But maybe it should not be done with only regular expressions though.
Not only will it be hard for yourself or other developers to work and add functionality on what would be a huge and super complex regular expression otherwise
it might even be that it is faster with this approach.
It might still need a lot of improvement but at least here is a working complete solution in a class. There is a bit more in here than asked in the question, but it illustrates some reasons behind some choices.
class mySearchToSql extends mysqli {
protected function filter($what) {
if (isset(what) {
//echo '<pre>Search string: '.var_export($what,1).'</pre>';//debug
//Split into different desires
preg_match_all('/([^"\-\s]+)|(?:"([^"]+)")|-(\S+)/i',$what,$split);
//echo '<pre>'.var_export($split,1).'</pre>';//debug
//Surround with SQL
array_walk($split[1],'self::sur',array('`Field` LIKE "%','%"'));
array_walk($split[2],'self::sur',array('`Desc` REGEXP "[[:<:]]','[[:>:]]"'));
array_walk($split[3],'self::sur',array('`Desc` NOT LIKE "%','%"'));
//echo '<pre>'.var_export($split,1).'</pre>';//debug
//Add AND or OR
$this ->where($split[3])
->where(array_merge($split[1],$split[2]), true);
}
}
protected function sur(&$v,$k,$sur) {
if (!empty($v))
$v=$sur[0].$this->real_escape_string($v).$sur[1];
}
function where($s,$OR=false) {
if (empty($s)) return $this;
if (is_array($s)) {
$s=(array_filter($s));
if (empty($s)) return $this;
if($OR==true)
$this->W[]='('.implode(' OR ',$s).')';
else
$this->W[]='('.implode(' AND ',$s).')';
} else
$this->W[]=$s;
return $this;
}
function showSQL() {
echo $this->W? 'WHERE '. implode(L.' AND ',$this->W).L:'';
}
Thanks for all stackoverflow answers to get here!
You're in luck because I asked a similar question regarding string literals recently. You can find it here: Regex for managing escaped characters for items like string literals
I ended up using the following for searching for them and it worked perfectly:
(?<!\\)(?:\\\\)*(\"|')((?:\\.|(?!\1)[^\\])*)\1
This regex differs from the others as it properly handles escaped quotation marks inside the string.