Say I have the following array and string:
$array = array('$AA', '$AB', '$AC', '$ZZ');
$string = 'String mentioning $AA and $AB and $CZ and $MARTASS';
I want to check $string for matches against $array. Every word in $string that begins with "$" should be checked. In the example, a match is found for $AA and $AB; not for $CZ. The desired output would be:
String mentioning {MATCH} and {MATCH} and {NO-MATCH}
Is this possible with one regex or is it better to write several lines of PHP? Any input is kindly received :)
Should be possible with two find-and-replaces, done in this order:
first:
\b(($AA)|($AB)|($AC)|($ZZ))\b ---> {MATCH}
second:
\b$\w+\b ---> {NO-MATCH}
I'm not sure this is in PHP syntax, but it shouldn't be too hard to get there. \b is a word separator boundary, which I believe is allowed in PHP.
Edit: You might need to escape $, not sure as it's grouped.
Yes it is possible. Have a look at the examples in the preg_replace_callback() documentation. You would use a replace call of the form:
function substituteVar($matches) {
...
}
...
$newString = preg_replace_callback("/\\$(\w+)/", 'substituteVar', $string);
I think I'll leave the content of the substituteVar() as an "exercise for the reader". :-)
This should work...
<?php
$string = 'String mentioning $AA and $AB and $CZ and $MARTASS';
echo preg_replace_callback("/\\$\S+/",
create_function('$a','return in_array($a[0],array("\$AA", "\$AB", "\$AC", "\$ZZ")) ? "{MATCH}" : "{NO-MATCH}";'),
$string
);
?>
Regex matches $ followed by one or more not spaces (\S+) and then checks if the matched string is in the array (included in create function definition so it is in scope, and escaped properly)
I wouldn't bother using a regex here, a simple scan of the string from start to finish, looking for the '$' character and then performing a binary search on the array would be much simpler and faster.
Related
I have a string that contains something like "LAB_FF, LAB_FF12" and I'm trying to use preg_replace to look for both patterns and replace them with different strings using a pattern match of;
/LAB_[0-9A-F]{2}|LAB_[0-9A-F]{4}/
So input would be
LAB_FF, LAB_FF12
and the output would need to be
DAB_FF, HAD_FF12
Problem is, for the second string, it interprets it as "LAB_FF" instead of "LAB_FF12" and so the output is
DAB_FF, DAB_FF
I've tried splitting the input line out using 2 different preg_match statements, the first looking for the {2} pattern and the second looking for the {4} pattern. This sort of works in that I can get the correct output into 2 separate strings but then can't combine the two strings to give the single amended output.
\b is word boundary. Meaning it will look at where the word ends and not only pattern match.
https://regex101.com/r/upY0gn/1
$pattern = "/\bLAB_[0-9A-F]{2}\b|\bLAB_[0-9A-F]{4}\b/";
Seeing the comment on the other answer about how to replace the string.
This is one way.
The pattern will create empty entries in the output array for each pattern that fails.
In this case one (the first).
Then it's just a matter of substr.
$re = '/(\bLAB_[0-9A-F]{2}\b)|(\bLAB_[0-9A-F]{4}\b)/';
$str = 'LAB_FF12';
preg_match($re, $str, $matches);
var_dump($matches);
$substitutes = ["", "DAB", "HAD"];
For($i=1; $i<count($matches); $i++){
If($matches[$i] != ""){
$result = $substitutes[$i] . substr($matches[$i],3);
Break;
}
}
Echo $result;
https://3v4l.org/gRvHv
You can specify exact amounts in one set of curly braces, e.g. `{2,4}.
Just tested this and seems to work:
/LAB_[0-9A-F]{2,4}/
LAB_FF, LAB_FFF, LAB_FFFF
EDIT: My mistake, that actually matches between 2 and 4. If you change the order of your selections it matches the first it comes to, e.g.
/LAB_([0-9A-F]{4}|[0-9A-F]{2})/
LAB_FF, LAB_FFFF
EDIT2: The following will match LAB_even_amount_of_characters:
/LAB_([0-9A-F]{2})+/
LAB_FF, LAB_FFFF, LAB_FFFFFF...
I am trying to parse a badly formed html table:
A couple of lines of this are:
Food:</b> Yes<b><br>
Pool: </b>Beach<b></b><b><br>
Centre:</b> Yes<b><br>
After spending a lot of time on this with Xpath, I think it is probably better to split the above text into lines use preg_split and parse from there.
The pattern I think would work uses:
<\b><\br>*: <\b>
my code is as follows:
$pattern='</b></br>*:</b>';
$pattern=preg_quote($pattern,'#');
$chars = preg_split($pattern, $output);
print_r($chars);
I am getting the following error:
Delimiter must not be alphanumeric or backslash
What I am doing wrong?
Try this:
$pattern='</b></br>*:</b>';
$pattern=preg_quote($pattern,'#');
$chars = preg_split('#'.$pattern.'#', $output);
print_r($chars);
The preg_quote function just makes it safely escaped, it doesn't actually add the delimiters for you.
As other people will surely point out, using regular expressions is not a good way to parse HTML :)
Your regular expression is also not going to match what you hope. Here's a version that will probably work for your input:
$in = " Pool: </b>Beach<b></b><b><br>";
$out = explode(':', strip_tags($in));
$key = trim($out[0]);
$value = trim($out[1]);
echo "$key = $value\n";
This removes all the HTML, then splits on the colon, and then removes any surrounding whitespace.
Your pattern needs to start and end with a delimiter; looks like you're using # if I'm reading this correctly, so you should have $pattern = '#</b></br>.*:</b>#';.
Also, you're mixing things up; * is not a simple wildcard in regex. If you mean "any number of any characters," the pattern you need is .*. I've included this above.
How can I replace a string starting with 'a' and ending with 'z'?
basically I want to be able to do the same thing as str_replace but be indifferent to the values in between two strings in a 'haystack'.
Is there a built in function for this? If not, how would i go about efficiently making a function that accomplishes it?
That can be done with Regular Expression (RegEx for short).
Here is a simple example:
$string = 'coolAfrackZInLife';
$replacement = 'Stuff';
$result = preg_replace('/A.*Z/', $replacement, $string);
echo $result;
The above example will return coolStuffInLife
A little explanation on the givven RegEx /A.*Z/:
- The slashes indicate the beginning and end of the Regex;
- A and Z are the start and end characters between which you need to replace;
- . matches any single charecter
- * Zero or more of the given character (in our case - all of them)
- You can optionally want to use + instead of * which will match only if there is something in between
Take a look at Rubular.com for a simple way to test your RegExs. It also provides short RegEx reference
$string = "I really want to replace aFGHJKz with booo";
$new_string = preg_replace('/a[a-zA-z]+z/', 'boo', $string);
echo $new_string;
Be wary of the regex, are you wanting to find the first z or last z? Is it only letters that can be between? Alphanumeric? There are various scenarios you'd need to explain before I could expand on the regex.
use preg_replace so you can use regex patterns.
I'm trying to replace all \n's sans that final one with \n\t in order to nicely indent for a recursive function.
This
that
then
thar
these
them
should become:
This
that
then
thar
these
them
This is what I have: preg_replace('/\n(.+?)\n/','\n\t$1\n',$var);
It currently spits this out:
This
that
then
thar
these
them
Quick Overview:
Need to indent every line less the first and last line using regex, how can I accomplish this?
You can use a lookahead:
$var = preg_replace('/\n(?=.*?\n)/', "\n\t", $var);
See it working here: ideone
After fixing a quotes issue, your output is actually like this:
This
that
then
thar
these
them
Use a positive lookahead to stop that trailing \n from getting eaten by the search regex. Your "cursor" was already set beyond it so only every other line was being rewritten; your match "zones" overlapped.
echo preg_replace('/\n(.+?)(?=\n)/', "\n\t$1", $input);
// newline-^ ^-text ^-lookahead ^- replacement
Live demo.
preg_replace('/\n(.+?)(?=\n)/',"\n\t$1",$var);
Modified the second \n to be the lookahead (?=\n), otherwise you'd run into issues with regex not recognizing overlapping matches.
http://ideone.com/1JHGY
Let the downwoting begin, but why use regex for this?
<?php
$e = explode("\n",$oldstr);
$str = $e[count($e) - 1];
unset($e[count($e) - 1]);
$str = implode("\n\t",$e)."\n".$str;
echo $str;
?>
Actually, str_replace has a "count" parameter, but I just can't seem to get it to work with php 5.3.0 (found a bug report). This should work:
<?php
$count = substr_count($oldstr,"\n") - 1;
$newstr = str_replace("\n","\n\t",$oldstr,&$count);
?>
i'v got such string <>1 <>2 <>3
i want remove all '<>' and symbols after '<>' i want replace with such expression like www.test.com/1.jpg, www.test.com/2.jpg, www.test.com/3.jpg
is it possible to do with regex? i only know to find '/<>.?/'
preg_replace('/<>(\d+)/g', 'www.test.com/bla/$1.jpg', $input);
(assuming your replaced elements are just numbers. If they are more general, you'll need to replace '\d+' by something else).
str_replace('<>', 'www.test.com/', $input);
// pseudo code
pre_replace_all('~<>([0-9]+)~', 'www.test.com/$1.jpg', $input);
$string = '<>1 <>2 <>3';
$temp = explode(' ',preg_replace('/<>(\d)/','www.test.com/\1.jpg',$string));
$newString = implode(', ',$temp);
echo $newString;
Based on your example, I don’t think you need regex at all.
$str = '<>1 <>2 <>3';
print_r(str_replace('<>', 'www.test.com/', $str));
Regex's allow you to manipulate a string in any fashion you desire, to modify the string in the fashion you desire you would use the following regex:
<>(\d)
and you would use regex back referencing to keep the values you have captured in your grouping brackets, in this case a single digit. The back reference is typically signified by the $ symbol and then the number of the group you are referencing. As follows:
www.test.com/$1
this would be used in a regex replace scenario which would be implemented in different ways depending on the language you are implementing your regex replace method in.