hello need help in regex i use this to split strings with capital letters like OldMcDonald
preg_split('/(?=[A-Z])/', $data, -1, PREG_SPLIT_NO_EMPTY);
output
[0] => Old
[1] => Mc
[2] => Donald
now i need to split strings like MWTTH
i need to tell the regex that a T with a letter H is one word how can i apply in my regex?
need the output:
[0] => M
[1] => w
[2] => T
[3] => TH
when i tried
$array = preg_split('/(?=[A-Z][TH])/', $data, -1, PREG_SPLIT_NO_EMPTY);
Output is
Array
(
[0] => MTW
[1] => F
[2] => TH
)
MTH Does not break appart, No time to study regex now.
I should have studied a little further i could have got it, anyway i already found it out i used:
$data = 'MTWFTH';
$array = preg_split('/(?=TH|M|T|W|F|S)/', $data, -1, PREG_SPLIT_NO_EMPTY);
OUTPUT
array (size=5)
0 => string 'M' (length=1)
1 => string 'T' (length=1)
2 => string 'W' (length=1)
3 => string 'F' (length=1)
4 => string 'TH' (length=2)
while this will only work for predefined data like mine.
No time to study regex... So, you are basically asking us to figure out the problem for you.
It took about 5 seconds to figure it out, 30 seconds to write it down, and 5 more seconds to copy and paste it:
$string = 'OldMcMWTTHDonald';
preg_match_all('/(?:TH|[A-Z][a-z]*)/', $string, $matches);
var_dump($matches);
You just wasted 40 seconds of my life.
Related
I want to split the text 'MTWTHFSSU' days of the week and store it in an array.
So far I am using this code using preg_split and REGEX.
$splitdays = preg_split('/(.H?)/',$days,null,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
print_r($splitdays);
array[0=>M, 1 => T, 2 => W, 3 => TH, 4 => F, 5 => S, 6 => S, 7 => U]
//this is my output
//if i change (.U) i will get correct SUNDAY = 'SU' but TH will be => T, => H
Note that the . can match any character.
As an alternative, you can use a bit more precise match with preg_match_all and use a pattern with an alternation | to list the more specific matches at the beginning and use a character class to list the single character variations.
TH|SU|[MTWFS]
For example
$days = "MTWTHFSSU";
$pattern = "/TH|SU|[MTWFS]/";
preg_match_all($pattern, $days, $matches);
print_r($matches[0]);
Output
Array
(
[0] => M
[1] => T
[2] => W
[3] => TH
[4] => F
[5] => S
[6] => SU
)
This should do the trick
$days='MTWTHFSSU';
$splitdays = preg_split('/(.H|.U?)/',$days,null,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE);
print_r($splitdays);
#anubhava's more concise comment works as well
preg_split('/(.[HU]?)/',$days,null,PREG_SPLIT_NO_EMPTY|PREG_SPLIT_DELIM_CAPTURE)
I have a database full of strings that I'd like to split into an array. Each string contains a list of directions that begin with a letter (U, D, L, R for Up, Down, Left, Right) and a number to tell how far to go in that direction.
Here is an example of one string.
$string = "U29R45U2L5D2L16";
My desired result:
['U29', 'R45', 'U2', 'L5', 'D2', 'L16']
I thought I could just loop through the string, but I don't know how to tell if the number is one or more spaces in length.
You can use preg_split to break up the string, splitting on something which looks like a U,L,D or R followed by numbers and using the PREG_SPLIT_DELIM_CAPTURE to keep the split text:
$string = "U29R45U2L5D2L16";
print_r(preg_split('/([UDLR]\d+)/', $string, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY));
Output:
Array (
[0] => U29
[1] => R45
[2] => U2
[3] => L5
[4] => D2
[5] => L16
)
Demo on 3v4l.org
A regular expression should help you:
<?php
$string = "U29R45U2L5D2L16";
preg_match_all("/[A-Z]\d+/", $string, $matches);
var_dump($matches);
Because this task is about text extraction and not about text validation, you can merely split on the zer-width position after one or more digits. In other words, match one or more digits, then forget them with \K so that they are not consumed while splitting.
Code: (Demo)
$string = "U29R45U2L5D2L16";
var_export(
preg_split(
'/\d+\K/',
$string,
0,
PREG_SPLIT_NO_EMPTY
)
);
Output:
array (
0 => 'U29',
1 => 'R45',
2 => 'U2',
3 => 'L5',
4 => 'D2',
5 => 'L16',
)
I tried multiple time to make a pattern that can validate given string is natural number and split into single number.
..and lack of understanding of regex, the closest thing that I can imagine is..
^([1-9])([0-9])*$ or ^([1-9])([0-9])([0-9])*$ something like that...
It only generates first, last, and second or last-second split-numbers.
I wonder what I need to know to solve this problem.. thanks
You may use a two step solution like
if (preg_match('~\A\d+\z~', $s)) { // if a string is all digits
print_r(str_split($s)); // Split it into chars
}
See a PHP demo.
A one step regex solution:
(?:\G(?!\A)|\A(?=\d+\z))\d
See the regex demo
Details
(?:\G(?!\A)|\A(?=\d+\z)) - either the end of the previous match (\G(?!\A)) or (|) the start of string (^) that is followed with 1 or more digits up to the end of the string ((?=\d+\z))
\d - a digit.
PHP demo:
$re = '/(?:\G(?!\A)|\A(?=\d+\z))\d/';
$str = '1234567890';
if (preg_match_all($re, $str, $matches)) {
print_r($matches[0]);
}
Output:
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 7
[7] => 8
[8] => 9
[9] => 0
)
I need to split a given user string into an array based around mathematical operators. The symbols I need the string splitting around are:
+
-
/
*
()
However I would like to expand on the regex to include other operators I will be adding into my program.
The regex I have so far is this:
"((\(|\d+.+|-|\*|\/\d+\|))"
which when ran through regex101.com matches a given input string of:
(30*30)/(9+8) with '30*30)/(9+8)
I would like the output to be similar to this:
[0] =
[1] = (
[2] = 30
[3] = *
[4] = 30
[5] = )
or:
[0] =
[1] = 4
[2] = *
[3] = 4
depending on whether brackets are present in the user string or not.
I forgot to include current results of the current regex string:
using http://www.phpliveregex.com/ to test preg-split with an input string of:
(30*30)+(9*8)
the result:
array(3
0 =>
1 =>
2 =>
)
Is this the pattern you are looking for?
preg_match_all("/(\(|-\d+|\d+|-|\+|\/|\*|\))/", $input, $output);
https://regex101.com/r/acKW27/3
Preg_match_all: http://www.phpliveregex.com/p/l7L
I forgot / in the regex. Links updated also.
preg_split() retains the delimiters by using the PREG_SPLIT_DELIM_CAPTURE flag. Include the additional flag PREG_SPLIT_NO_EMPTY to eliminate any empty elements. Here is an improved answer that will handle your sample input data, as well as floats and negative numbers.
Code: (Demo)
$expression = '-1*(2/(3+4)--10*-110.5/0.009+-.1)';
var_export(
preg_split(
'~(-?\d*(?:\.\d+)?|[()*/+-])~',
$expression,
0,
PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE
)
);
Output:
array (
0 => '-1',
1 => '*',
2 => '(',
3 => '2',
4 => '/',
5 => '(',
6 => '3',
7 => '+',
8 => '4',
9 => ')',
10 => '-',
11 => '-10',
12 => '*',
13 => '-110.5',
14 => '/',
15 => '0.009',
16 => '+',
17 => '-.1',
18 => ')',
)
*Note, my above pattern makes digits before the decimal optional. If you know that your floats will always have a number before the dot, then you can use this pattern:
~(-?\d+(?:\.\d+)?|[()*/+-])~
The advantages are: no empty matches, no need for PREG_SPLIT_NO_EMPTY, and improved pattern efficiency.
Let's take an example of following string:
$string = "length:max(260):min(20)";
In the above string, :max(260):min(20) is optional. I want to get it if it is present otherwise only length should be returned.
I have following regex but it doesn't work:
/(.*?)(?::(.*?))?/se
It doesn't return anything in the array when I use preg_match function.
Remember, there can be something else than above string. Maybe like this:
$string = "number:disallow(negative)";
Is there any problem in my regex or PHP won't return anything? Dumping preg_match returns int 1 which means the string matches the regex.
Fully Dumped:
int 1
array (size=2)
0 => string '' (length=0)
1 => string '' (length=0)
You're using single character (.) matching in the case of being lazy, at the very beginning. So it stops at the zero position. If you change your preg_match function to preg_match_all you'll see the captured groups.
Another problem is with your Regular Expression. You're killing the engine. Also e modifier is deprecated many many decades before!!! and yet it was used in preg_replace function only.
Don't use s modifier too! That's not needed.
This works at your case:
/([^:]+)(:.*)?/
Online demo
I tried to prepare a regex which can probably solve your issue and also add some value to it
this regex will not only match the optional elements but will also capture in key value pair
Regex
/(?<=:|)(?'prop'\w+)(?:\((?'val'.+?)\))?/g
Test string
length:max(260):min(20)
length
number:disallow(negative)
Result
MATCH 1
prop [0-6] length
MATCH 2
prop [7-10] max
val [11-14] 260
MATCH 3
prop [16-19] min
val [20-22] 20
MATCH 4
prop [24-30] length
MATCH 5
prop [31-37] number
MATCH 6
prop [38-46] disallow
val [47-55] negative
try demo here
EDIT
I think I understand what you meant by duplicate array with different key, it was due to named captures eg. prop & val
here is the revision without named capturing
Regex
/(?<=:|)(\w+)(?:\((.+?)\))?/
Sample code
$str = "length:max(260):min(20)";
$str .= "\nlength";
$str .= "\nnumber:disallow(negative)";
preg_match_all("/(?<=:|)(\w+)(?:\((.+?)\))?/",
$str,
$matches);
print_r($matches);
Result
Array
(
[0] => Array
(
[0] => length
[1] => max(260)
[2] => min(20)
[3] => length
[4] => number
[5] => disallow(negative)
)
[1] => Array
(
[0] => length
[1] => max
[2] => min
[3] => length
[4] => number
[5] => disallow
)
[2] => Array
(
[0] =>
[1] => 260
[2] => 20
[3] =>
[4] =>
[5] => negative
)
)
try demo here