I have a set of strings like below :
fw-sophi.watcon.-.120
d-elain.heckop.-.121
sim.boosh.-.134
bh.-.elain.heckop.-.244
How would I trim the following set of strings to return only the middle section?
expected return:
sophi.watcon
elain.heckop
sim.boosh
elain.heckop
It isn't practical to trim() the strings manually as there are a lot, how would I do this Programmatically ?
If there are no other patterns, this should be sufficient:
$input = 'fw-sophi.watcon.-.120
d-elain.heckop.-.121
sim.boosh.-.134
bh.-.elain.heckop.-.244';
if (preg_match_all('~(?<key>\w+\.\w+)~', $input, $matches)) {
print_r($matches['key']);
}
Resulting array:
Array
(
[0] => sophi.watcon
[1] => elain.heckop
[2] => sim.boosh
[3] => elain.heckop
)
Pattern explanation:
~ #pattern start
( #start group to capture matched result
?<key> #give a name to group. see $matches['key'].
\w+ #one or more alphanumeric characters
\. #dot character. we need to escape it with \
\w+ #one or more alphanumeric characters
) #end group
~ #pattern end
x
Related
I have a placeholder in my content which has the following format
{{label1#label2_label3}}}
And I'm correctly matching it with this regex
preg_match('/\{\{(\w+|d+|_+|#+)*\}\}/i', $content, $matches);
The problem is that the $matches array which PHP returns has the following data (preg_match docs)
array (size=2)
0 => string '{{label1#label2_label3}}' (length=44)
1 => string 'label2_label3' (length=16)
While my expected output is the following
array (size=2)
0 => string '{{label1#label2_label3}}' (length=44)
1 => string 'label1#label2_label3' (length=16)
My solution was to use a replace to simply get rid of the parenthesis like so:
$matches[1] = str_replace("}", "", (str_replace("{","",$matches[0])));
which works but I'm concerned about the performance while rendering a page with many placeholders.
Is there any flag or function I'm missing to just tell PHP to return the entire string inside {{ }} in $matches1?
Using \w also matches \d and _ so that will leave \w and #
You get that result where label1# is missing as you repeat a capture group which will capture the value of the last iteration.
As you want a match for label1#label2_label3 you can use a single character class to match word characters and the # char and use a non repeating capture group.
{{([\w#]+)}}
Regex demo | PHP demo
$content = "{{label1#label2_label3}}";
preg_match('/{{([\w#]+)}}/i', $content, $matches);
print_r($matches);
Output
Array
(
[0] => {{label1#label2_label3}}
[1] => label1#label2_label3
)
If the # and _ can not be at the start or at the end:
{{([^\W_]+(?:[_#][^\W_]+)*)}}
The pattern in parts:
{{ Match literally
( Capture group 1
[^\W_]+ Match 1+ word characters without _
(?:[_#][^\W_]+)* Optionally repeat matching either _ or # and 1+ word characters without _
) Close group 1
}} Match literally
Regex demo
I need to get the float number inside brackets..
I tried this '([0-9]*[.])?[0-9]+' but it returns the first number like 6 in the first example.
Also I tried this
'/\((\d+)\)/'
but it returns 0.
Please note that I need the extracted number either int or float.
Can u plz help
As you need to match bracket also, You need to add () in regular expression:
$str = 'Serving size 6 pieces (40)';
$str1 = 'Per bar (41.5)';
preg_match('#\(([0-9]*[.]?[0-9]+)\)#', $str, $matches);
print_r($matches);
preg_match('#\(([0-9]*[.]?[0-9]+)\)#', $str1, $matches);
print_r($matches);
Output:
Array
(
[0] => (40)
[1] => 40
)
Array
(
[0] => (41.5)
[1] => 41.5
)
DEMO
You could escape brackets:
$str = 'Serving size 6 pieces (41.5)';
if (preg_match('~\((\d+.?\d*)\)~', $str, $matches)) {
print_r($matches);
}
Outputs:
Array
(
[0] => (41.5)
[1] => 41.5
)
Regex:
\( # open bracket
( # capture group
\d+ # one or more numbers
.? # optional dot
\d* # optional numbers
) # end capture group
\) # close bracket
You could also use this to get only one digit after the dot:
'~\((\d+.?\d?)\)~'
You need to escape the brackets
preg_match('/\((\d+(?:\.\d+)?)\)/', $search, $matches);
explanation
\( escaped bracket to look for
( open subpattern
\d a number
+ one or more occurance of the character mentioned
( open Group
?: dont save data in a subpattern
\. escaped Point
\d a number
+ one or more occurance of the character mentioned
) close Group
? one or no occurance of the Group mentioned
) close subpattern
\) escaped closingbracket to look for
matches numbers like
1,
1.1,
11,
11.11,
111,
111.111 but NOT .1, .
https://regex101.com/r/ei7bIM/1
You could match an opening parenthesis, use \K to reset the starting point of the reported match and then match your value:
\(\K\d+(?:\.\d+)?(?=\))
That would match:
\( Match (
\K Reset the starting point of the reported match
\d+ Match one or more digits
(?: Non capturing group
\.\d+ Match a dot and one or more digits
)? Close non capturing group and make it optional
(?= Positive lookahead that asserts what follows is
\) Match )
) Close posive lookahead
Demo php
I've found several partial answers to this question, but none that cover all my needs...
I am trying to parse a user generated string as if it were a series of php function arguments to determine the number of arguments:
This string:
$arg1,$arg2='ABC,DEF',$arg3="GHI\",JKL",$arg4=array(1,'2)',"3\"),")
will be inserted as the arguments of a function:
function my_function( [insert string here] ){ ... }
I need to parse the string on the commas, taking into account single- and double-quotes, parentheses, and escaped quotes and parentheses to create an array:
array(4) {
[0] => $arg1
[1] => $arg2='ABC,DEF'
[2] => $arg3="GHI\",JKL"
[3] => $arg4=array(1,'2)',"3\"),")
}
Any help with a regular expression or parser function to accomplish this is appreciated!
It isn't possible to solve this problem with a classical csv tool since there is more than one character able to protect parts of the string.
Using preg_split is possible but will result in a very complicated and inefficient pattern. So the best way is to use preg_match_all. There are however several problems to solve:
as needed, a comma enclosed in quotes or parenthesis must be ignored (seen as a character without special meaning, not as a delimiter)
you need to extract the params, but you need to check if the string has the good format too, otherwise the match results may be totally false!
For the first point, you can define subpatterns to describe each cases: the quoted parts, the parts enclosed between parenthesis, and a more general subpattern able to match a complete param and that uses the two previous subpatterns when needed.
Note that the parenthesis subpattern needs to refer to the general subpattern too, since it can contain anything (and commas too).
The second point can be solved using the \G anchor that ensures that all matchs are contiguous. But you need to be sure that the end of the string has been reached. To do that, you can add an optional empty capture group at the end of the main pattern that is created only if the anchor for the end of the string \z succeeds.
$subject = <<<'EOD'
$arg1,$arg2='ABC,DEF',$arg3="GHI\",JKL",$arg4=array(1,'2)',"3\"),")
EOD;
$pattern = <<<'EOD'
~
# named groups definitions
(?(DEFINE) # this definition group allows to define the subpatterns you want
# without matching anything
(?<quotes>
' [^'\\]*+ (?s:\\.[^'\\]*)*+ ' | " [^"\\]*+ (?s:\\.[^"\\]*)*+ "
)
(?<brackets> \( \g<content> (?: ,+ \g<content> )*+ \) )
(?<content> [^,'"()]*+ # ' # (<-- comment for SO syntax highlighting)
(?:
(?: \g<brackets> | \g<quotes> )
[^,'"()]* # ' #
)*+
)
)
# the main pattern
(?: # two possible beginings
\G(?!\A) , # a comma contiguous to a previous match
| # OR
\A # the start of the string
)
(?<param> \g<content> )
(?: \z (?<check>) )? # create an item "check" when the end is reached
~x
EOD;
$result = false;
if ( preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER) &&
isset(end($matches)['check']) )
$result = array_map(function ($i) { return $i['param']; }, $matches);
else
echo 'bad format' . PHP_EOL;
var_dump($result);
demo
You could split the argument string at ,$ and then append $ back the array values:
$args_array = explode(',$', $arg_str);
foreach($args_array as $key => $arg_raw) {
$args_array[$key] = '$'.ltrim($arg_raw, '$');
}
print_r($args_array);
Output:
(
[0] => $arg1
[1] => $arg2='ABC,DEF'
[2] => $arg3="GHI\",JKL"
[3] => $arg4=array(1,'2)',"3\"),")
)
If you want to use a regex, you can use something like this:
(.+?)(?:,(?=\$)|$)
Working demo
Php code:
$re = '/(.+?)(?:,(?=\$)|$)/';
$str = "\$arg1,\$arg2='ABC,DEF',\$arg3=\"GHI\",JKL\",\$arg4=array(1,'2)',\"3\"),\")\n";
preg_match_all($re, $str, $matches);
Match information:
MATCH 1
1. [0-5] `$arg1`
MATCH 2
1. [6-21] `$arg2='ABC,DEF'`
MATCH 3
1. [22-39] `$arg3="GHI\",JKL"`
MATCH 4
1. [40-67] `$arg4=array(1,'2)',"3\"),")`
I'm attempting to pull a certain part out of different varying strings, and am having a really hard time getting the correct regex to do so. Here are a few examples of what I am trying to pull from:
AG055.MA - MAGNUM (Want to return just MA)
WI460.16 - SOMETHING (Want to return 16)
AG055.QB (Want to return QB)
So basically, I just want to pull the characters after the period, but before the space. Nothing else before or after. Can someone give me a hand with getting the correct regex?
This should work:
<?php
preg_match( '/\.([^ ]+)/', $text, $matches );
print_r( $matches );
?>
Output:
Array
(
[0] => .MA
[1] => MA
)
Array
(
[0] => .16
[1] => 16
)
Array
(
[0] => .QB
[1] => QB
)
The regex is saying find a . character, then get any characters after it that are not a space character. The + makes it only return matches where there is a non-space character after the dot.
preg_match('/\w+\.(\w{2})\s/', $input, $matches);
echo $matches[1];
\w+ means 1 or more word characters (a-z, A-Z and 0-9).
\. means the period/dot (the backslash is to escape it, because \. is used as an operator in regex)
(\w{2}) matches 2 word characters
\s means whitespace
preg_match('/^[A-Z0-9]{5}\.([A-Z0-9]{2})/', $string, $matches);
var_dump($matches);
Should return the characters in $matches[1].
i am seriously struggling to get my head around regex.
I have a sring with "iPhone: 52.973053,-0.021447"
i want to extract the two numbers after the colon into two seperate strings so delimited by the comma.
Can anyone help me? Cheers
Try:
preg_match_all('/\w+:\s*(-?\d+\.\d+),(-?\d+\.\d+)/',
"iPhone: 52.973053,-0.021447 FOO: -1.0,-1.0",
$matches, PREG_SET_ORDER);
print_r($matches);
which produces:
Array
(
[0] => Array
(
[0] => iPhone: 52.973053,-0.021447
[1] => 52.973053
[2] => -0.021447
)
[1] => Array
(
[0] => FOO: -1.0,-1.0
[1] => -1.0
[2] => -1.0
)
)
Or just:
preg_match('/\w+:\s*(-?\d+\.\d+),(-?\d+\.\d+)/',
"iPhone: 52.973053,-0.021447",
$match);
print_r($match);
if the string only contains one coordinate.
A small explanation:
\w+ # match a word character: [a-zA-Z_0-9] and repeat it one or more times
: # match the character ':'
\s* # match a whitespace character: [ \t\n\x0B\f\r] and repeat it zero or more times
( # start capture group 1
-? # match the character '-' and match it once or none at all
\d+ # match a digit: [0-9] and repeat it one or more times
\. # match the character '.'
\d+ # match a digit: [0-9] and repeat it one or more times
) # end capture group 1
, # match the character ','
( # start capture group 2
-? # match the character '-' and match it once or none at all
\d+ # match a digit: [0-9] and repeat it one or more times
\. # match the character '.'
\d+ # match a digit: [0-9] and repeat it one or more times
) # end capture group 2
A solution without using regular expressions, using explode() and stripos() :) :
$string = "iPhone: 52.973053,-0.021447";
$coordinates = explode(',', $string);
// $coordinates[0] = "iPhone: 52.973053"
// $coordinates[1] = "-0.021447"
$coordinates[0] = trim(substr($coordinates[0], stripos($coordinates[0], ':') +1));
Assuming that the string always contains a colon.
Or if the identifier before the colon only contains characters (not numbers) you can do also this:
$string = "iPhone: 52.973053,-0.021447";
$string = trim($string, "a..zA..Z: ");
//$string = "52.973053,-0.021447"
$coordinates = explode(',', $string);
Try:
$string = "iPhone: 52.973053,-0.021447";
preg_match_all( "/-?\d+\.\d+/", $string, $result );
print_r( $result );
I like #Felix's non-regex solution, I think his solution for the problem is more clear and readable than using a regex.
Don't forget that you can use constants/variables to change the splitting by comma or colon if the original string format is changed.
Something like
define('COORDINATE_SEPARATOR',',');
define('DEVICE_AND_COORDINATES_SEPARATOR',':');
$str="iPhone: 52.973053,-0.021447";
$s = array_filter(preg_split("/[a-zA-Z:,]/",$str) );
print_r($s);
An even more simple solution is to use preg_split() with a much more simple regex, e.g.
$str = 'iPhone: 52.973053,-0.021447';
$parts = preg_split('/[ ,]/', $str);
print_r($parts);
which will give you
Array
(
[0] => iPhone:
[1] => 52.973053
[2] => -0.021447
)