Remove all text except specific text and value Regex - php

I have a problem with RegEX. I have output like this.
Number of rooms
2
Price
120000
Square in meter
60
I’m trying to achieve this: I want remove all text except “Number of rooms 2” My value “2” changes. So far I have expression like this:
<?php
$str = get_field('all');
preg_match('/ Number of rooms \s*(\d+)/' , $str, $matches);
echo $matches[1];
?>

Remove the preceding space before the Number word :
preg_match('/Number of rooms \s*(\d+)/' , $str, $matches);

Remove the Space before Number and after rooms in your regex:
$str = 'Number of rooms
2
Price
120000
Square in meter
60';
preg_match('/Number of rooms\s*(\d+)/' , $str, $matches);
print_r($matches);
output:
Array
(
[0] => Number of rooms
2
[1] => 2
)

As the others has said it's the space. You can solve it with removing the space or make it optional with *.
I would advise to use regex options im also as it will be case insensitive and treat the string as multilined.
preg_match('/number of rooms\s*(\d+)/im', $str, $m);
var_dump($m);

you can try it this way:
$str = get_field('all');
$str_array = explode("\n",$str);
$new_str=$str_array[0]." ".$str_array[1];
echo $new_str;

Related

Regex to match a number followed by a specific string

I need to find a number followed by a specific string, within another string.
The initial string could be:
some text 0.25mcg some more text
some text 25mcg some more text
so the number could be a decimal. I need to be able to return the number (so 0.25 or 25) where ever the number is followed by 'mcg'
Can anyone help me out. This doesn't work:
if(preg_match('(\d+mcg)', $item, $match))
Another option is to capture a digit with an optional decimal part \d+(?:\.\d+)? and use a word boundary \b to prevent the match being part of a larger word.
\b(\d+(?:\.\d+)?)mcg\b
Regex demo | Php demo
Code example
$re = '/\b(\d+(?:\.\d+)?)mcg\b/';
$str = 'some text 0.25mcg some more text some text 25mcg some more text';
preg_match_all($re, $str, $matches);
print_r($matches[1]);
Output
Array
(
[0] => 0.25
[1] => 25
)
If you want a match only instead of a capturing group you might also opt for a positive lookahead (?= instead.
\b\d+(?:\.\d+)?(?=mcg\b)
Regex demo | Php demo
It's a job for preg_match_all
preg_match_all('/([\d.]+)mcg/', $item, $matches);
[\d.]+ matches 1 or more digits or dot.
here is simple version:
<?php
$item1 = 'some text 0.25mcg some more text';
$item2 = 'some text 25mcg some more text';
if (preg_match('/([0-9\\.]+)\\s*mcg/', $item1, $match)) echo $match[1] . '<br>';
if (preg_match('/([0-9\\.]+)\\s*mcg/', $item2, $match)) echo $match[1] . '<br>';

Regex match from right to left

I wanted to match something from right to left, below is one of such example.
100abababab3x3x3xx1000morewords
If i want to match something between and last xx and immediate previous ab and get 3x3x3
I tried something like below , but it matches ababab3x3x3
preg_match('/ab(.*?)xx/',$text,$totmat);
Note : please don't recommend strrev.
Above example is just for illustration , all i wanted to do is match from right to left.
Not sure this is the most optimized way or not? But this will work for you if you use the combination of Look ahead positive (?=) and Look behind positive (?<=). See regex
<?php
$re = '/\w+(?<=ab)(.*?)(?=xx)/m';
$str = '100abababab3x3x3xx1000morewords';
preg_match_all($re, $str, $matches, PREG_SET_ORDER, 0);
// Print the full matched result
echo $matches[0][1];
DEMO: https://3v4l.org/db69N
$str = '100abababab3x3x3xx1000morewords';
preg_match('/ab((?:(?!ab).)*)xx/', $str, $m);
print_r($m);
Output:
Array
(
[0] => ab3x3x3xx
[1] => 3x3x3
)
>Explanation:
ab : literally ab
( : start group 1
(?: : start non capture group
(?!ab) : negative lookahead, make sure we doon't have ab
. : any character but newline
)* : end group, may appear 0 or more times
) : end group 1
xx : literally xx
There are other approaches than a regex to this kind of problem that would be close to twice faster in computing time.
Here for example :
$str = "100abababab3x3x3xx1000morewords";
$result = explode("ab", explode("xx", $str)[0]);
var_dump(end($result));
First occurence of explode split the string in two between the "xx" characters. We're only interested by the left part (Index 0).
Second occurence of explode split the string with the caracters ab. We're only interested by the last occurence of ab. Therefore var_dump(end($result)); prints the expected result.

Get number before the percent sign

I have a string like that:
$string = "Half Board, 10% Off & 100 Euro Star - Save £535";
The percentage can be anywhere in the string.
This is what I have, but I don't like the fact that it has a preg_replace AND a loop operation, which are heavy. I'd like a ReGex expression that would do it in one operation.
$string = "Half Board, 10% Off & 100 Euro Star - Save £535";
$string_array = explode(" ", $string);
$pattern = '/[^0-9,.]*/'; // non-digits
foreach($string_array as $pc) {
if(stristr($pc, '%')) {
$percent = preg_replace($pattern, '', $pc);
break;
}
}
echo $percent;
exit;
Update:
From the code you added to your question, I get the impression your percentages might look like 12.3% or even .50%. In which case, the regex you're looking for is this:
if (preg_match_all('/(\d+|\d+[.,]\d{1,2})(?=\s*%)/','some .50% and 5% text with 12.5% random percentages and 123 digits',$matches))
{
print_r($matches);
}
Which returns:
Array
(
[0] => Array
(
[0] => .50
[1] => 5
[2] => 12.5
)
[1] => Array
(
[0] => .50
[1] => 5
[2] => 12.5
)
)
the expression explained:
(\d+|\d*[.,]\d{1,2}): is an OR -> either match digits \d+, or \d* zero or more digits, followed by a decimal separator ([.,]) and 1 or 2 digits (\d{1,2})
(?=\s*%): only if the afore mentioned group is followed by zero or more spaces and a % sign
Using a regular expression, with a positive lookahead, you can get exactly what you want:
if (preg_match_all('/\d+(?=%)/', 'Save 20% if you buy 5 iPhone charches (excluding 9% tax)', $matches))
{
print_r($matches[0]);
}
gives you:
array (
0 => '20',
1 => '9'
)
Which is, I believe, what you are looking for
The regex works like this:
\d+ matches at least 1 digit (as many as possible)
(?=%): provided they are followed by a % sign
Because of the lookahead, the 5 isn't matched in the example I gave, because it's followed by a space, not a % sign.
If your string might be malformed (have any number of spaces between the digit and the % sign) a lookahead can deal with that, too. As ridgerunner pointed out to me, only lookbehinds need to be of fixed size, so:
preg_match_all('/\d+(?=\s*%)/', $txt, $matches)
The lookahead works like this
\s*: matches zero or more whitespace chars
%: and percent sign
Hence, both 123 % and 123% fit the pattern, and will match.
A good place to read up on regex's is regular-expressions.info
If "complex" regex's (ie with lookaround assertions) aren't your cup of tea (yet, though I strongly suggest learning to use them), you could resort to splitting the string:
$parts = array_map('trim', explode('%', $string));
$percentages = array();
foreach($parts as $part)
{
if (preg_match('/\d+$/', $part, $match))
{//if is required, because the last element of $parts might not end with a number
$percentages[] = $match[0];
}
}
Here, I simply use the % as delimiter, to create an array, and trim each string section (to avoid trailing whitespace), and then procede to check each substring, and match any number that is on the end of that substring:
'get 15% discount'
['get 15', 'discount']
/\d+$/, 'get 15' = [15]
But that's just an awful lot of work, using a lookahead is just way easier.
$str = "Half Board, 10% Off & 100 Euro Star - Save £535";
preg_match("|\d+|", $str, $arr);
print_r($arr);
Try with split like
$str_arr = split(' ',$str);
$my_str = split('%',$str_arr[1]);
echo $my_str[0];
This should work:
$str = "Save 20% on iPhone chargers...";
if (preg_match_all('/\d+(?=%)/', $str, $match))
print_r($match[0]);
Live Demo: http://ideone.com/FLKtE9

Regex to split alphanumeric, currency and numeric terms in PHP

I am trying to split a string into terms in PHP using preg_split. I need to extract normal words ( \w ) but also currency ( even currency symbol ) and numeric terms ( including commas and decimal points ). Can anyone help me out, as I cannot seem to create a valid regex to use for preg_split to achieve this. Thanks
Why not use preg_match_all() instead of preg_split() ?
$str = '"1.545" "$143" "$13.43" "1.5b" "hello" "G9"'
. ' This is a test sentence, with some. 123. numbers'
. ' 456.78 and punctuation! signs.';
$digitsPattern = '\$?\d+(\.\d+)?';
$wordsPattern = '[[:alnum:]]+';
preg_match_all('/('.$digitsPattern.'|'.$wordsPattern.')/i', $str, $matches);
print_r($matches[0]);
What about preg_match_all() each word with this [\S]+\b then you get an array with the words in it.
Big brown fox - $20.25 will return
preg_match_all('/[\S]+\b/', $str, $matches);
$matches = array(
[0] = 'Big',
[1] = 'brown',
[2] = 'fox',
[3] = '$20.25'
)
Does it solve your problem to split on whitespace? "/\s+/"

Find phone numbers in a string

In PHP I'm searching for phonenumbers in a certain text.
I use explode() to divide the text in different parts,using the area code of the city I'm searching for as the delimiter. The problem is that phonenumbers that include the same numbers as the area-code are not returned well.
For example:
"foofoo 010-1234567 barbar" splits into "foofoo " and "-1234567 barbar"
but
"foofoo 010-1230107 barbar" splits into "foofoo ", "-123" and "7 barbar" !
I can use the first one to reconstruct the phonenummer with the areacode, but the second goes wrong of course...
I guess I need a regular expression to split the text with some kind of mechanism to not split on short strings, instead of explode() , but I don't know how to do it.
Any ideas or a better way to search for phonenumbers in a text ?
UPDATE:
The format is NOT consistent, so looking for the hyphen is no solution. Some phone numbers have spaces between the area code and number, some have hooks, some have nothing, etc. Dutch phonenumbers have an areacode of 2,3 or 4 numbers and are usually 10 numbers in total.
To find phone numbers like:
010-1234010
010 1234010
010 123 4010
0101234010
010-010-0100
Try this:
$text = 'foofoo 010-1234010 barbar 010 1234010 foofoo ';
$text .= ' 010 123 4010 barbar 0101234010 foofoo 010-010-0100';
$matches = array();
// returns all results in array $matches
preg_match_all('/[0-9]{3}[\-][0-9]{6}|[0-9]{3}[\s][0-9]{6}|[0-9]{3}[\s][0-9]{3}[\s][0-9]{4}|[0-9]{9}|[0-9]{3}[\-][0-9]{3}[\-][0-9]{4}/', $text, $matches);
$matches = $matches[0];
var_dump($matches);
You could use a regular expression to match the phone numbers. There are many, many ways to skin this particular cat (and likely many identical questions here on SO) a super-basic example might look like the following.
$subject = "foofoo 010-1230107 barbar 010-1234567";
preg_match_all('/\b010-\d+/', $subject, $matches);
$numbers = $matches[0];
print_r($numbers);
The above would output the contents of the $numbers array.
Array
(
[0] => 010-1230107
[1] => 010-1234567
)
If you delete all of the non numeric characters, you will only be left with the phone number. You can then take that string and parse it into ###-###-#### if you wish.
$phone = preg_replace('/\D/', '', 'Some test with 123-456-7890 that phone number');
//$phone is now 1234567890
echo substr($phone, 0, 3);//123
echo subsr($phone, 3, 3);//456
echo substr($phone, 6);//7890
Not sure if that is what you are looking for or not.

Categories