Match numbers separated with colons, semicolons optionally - php

I have the following string:
objectsA=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;:objectsB=
And I want to know how can I match, optionally, the numbers inside objectsA and objectsB but put into consideration, that may one or another can be empty. For example:
objectsA can be:
objectsA=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;
But also can be
objectsA=:objectsB=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;
Or even
objectsA=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;:objectsB=objectsA=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;
The current code:
$line2 = "
2016-07-31 00:39:00 debian-8gb-sfo2-01 gdeliveryd: notice : formatlog:trade:roleidA=3328:roleidB=2161:moneyA=0:moneyB=0:objectsA=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;:objectsB=";
if (strpos($line2, ':trade:roleidA=3328') > 0) {
if (!preg_match('/([\d-: ]+)\s*.*\sformatlog:trade:roleidA=(\d+):(.*)roleidB=(\d+):moneyA=(\d+):moneyB=(\d+):objectsA=(regexhere):objectsB=(regexhere).*$/', $line2, $c)) {
// error occured
}
echo '<pre>';
print_r($c);
}
And the problems is that the current regex ((\d+\,\d+\,\d\;)+|) has an weird behavior, that can't happen.
Output:
Array
(
[0] => 2016-07-31 00:39:00 debian-8gb-sfo2-01 gdeliveryd: notice : formatlog:trade:roleidA=3328:roleidB=2161:moneyA=0:moneyB=0:objectsA=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;:objectsB=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;
[1] => 2016-07-31 00:39:00
[2] => 3328
[3] =>
[4] => 2161
[5] => 0
[6] => 0
[7] => 38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;
[8] => 38155,39,1;
[9] => 38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;
[10] => 38155,39,1;
)
For some reason, if the objects has the same size, the regex are creating a new array index, wich shouldn't happen.
The expected result:
Array
(
[0] => 2016-07-31 00:39:00 debian-8gb-sfo2-01 gdeliveryd: notice : formatlog:trade:roleidA=3328:roleidB=2161:moneyA=0:moneyB=0:objectsA=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;:objectsB=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;
[1] => 2016-07-31 00:39:00
[2] => 3328
[4] => 2161
[5] => 0
[6] => 0
[7] => 38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;
[8] => 38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;
)

Regex: ^(?:\s?\d+(?:[-:]\d+){2}){2}|\w+=\K[^:]+
Details:
(?:) Non-capturing group
[] Match a single character present in the list
\K Resets the starting point of the reported match
+ Matches between one and unlimited times
| Or
PHP code:
$string = "2016-07-31 00:39:00 debian-8gb-sfo2-01 gdeliveryd: notice : formatlog:trade:roleidA=3328:roleidB=2161:moneyA=0:moneyB=0:objectsA=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;:objectsB=38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;";
preg_match_all('~^(?:\s?\d+(?:[-:]\d+){2}){2}|\w+=\K[^:]+~', $string, $matches);
print_r($matches[0]);
Output:
Array
(
[0] => 2016-07-31 00:39:00
[1] => 3328
[2] => 2161
[3] => 0
[4] => 0
[5] => 38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;
[6] => 38155,54,1;38155,53,1;38155,45,1;38155,47,1;38155,46,1;2000,55,1;38155,50,1;38155,49,1;38155,48,1;38155,40,1;38155,41,1;38155,42,1;38155,43,1;38155,51,1;38155,52,1;38155,44,1;38155,35,1;38155,33,1;38155,32,1;38155,34,1;38155,36,1;38155,38,1;38155,39,1;
)
Code demo

For are navigating through this question, sometimes: less is more. The pattern (.*) will do the trick.
([\d-: ]+)\s*.*\sformatlog:trade:roleidA=(\d+):roleidB=(\d+):moneyA=(\d+):moneyB=(\d+):objectsA=(.*):objectsB=(.*).*$

Related

How to split 1 array into 2 arrays, remove certain items, and combine them again into 1 array in PHP?

i want to create something using array. I have 1 array and i need to split it into 2 array. After that search specific items from both array and remove it then combine it 2 array into 1 array.
How do i do that?
I already try to use unset for array but confuse how to use it for specific key since my array data format like 16/2/1/1 and 16/2/1/5. I need to remove data which have 1.
My format array is like this
Array
(
[1] => Array
(
[0] => 16/2/1/1 --> remove this have 1 after 2
[1] => 16/2/0/2
[2] => 16/2/0/3
[3] => 16/2/0/4
[4] => 16/2/0/5
[5] => 16/2/0/6
[6] => 16/2/0/7
[7] => 16/2/0/8
[8] => 16/2/0/9
[9] => 16/2/0/10
[10] => 16/2/0/11
[11] => 16/2/0/12
[12] => 16/2/0/13
[13] => 16/2/0/14
[14] => 16/2/0/15
[15] => 16/2/0/16
)
[2] => Array
(
[0] => 16/2/0/1
[1] => 16/2/0/2
[2] => 16/2/0/3
[3] => 16/2/0/4
[4] => 16/2/1/5 --> and this have 1 after 2 before 5
[5] => 16/2/0/6
[6] => 16/2/0/7
[7] => 16/2/0/8
[8] => 16/2/0/9
[9] => 16/2/0/10
[10] => 16/2/0/11
[11] => 16/2/0/12
[12] => 16/2/0/13
[13] => 16/2/0/14
[14] => 16/2/0/15
[15] => 16/2/0/16
)
)
i expect the output something like (after combine)
Array
(
[0] => 16/2/0/2
[1] => 16/2/0/3
[2] => 16/2/0/4
[3] => 16/2/0/6
[4] => 16/2/0/7
[5] => 16/2/0/8
[6] => 16/2/0/9
[7] => 16/2/0/10
[8] => 16/2/0/11
[9] => 16/2/0/12
[10] => 16/2/0/13
[11] => 16/2/0/14
[12] => 16/2/0/15
[13] => 16/2/0/16
)
Thanks for time to help me.
Make the array unique and then extract items that are digits/digits/NOT 1/digits:
$array = preg_grep('#^\d+/\d+/[^1]/\d+#', array_unique($array));
I would use preg_grep which allows you to search an array using a Regular expression.
$array =[
'16/2/0/13',
'16/2/0/16',
'16/2/1/5'
];
$array = preg_grep('~^16/2/0/\d+$~', $array);
print_r($array);
Output
Array
(
[0] => 16/2/0/13
[1] => 16/2/0/16
)
Sandbox
The Regex
^ match start of string
16/2/0/ - match literally (at the start of string, see above)
\d+ any digit one or more
$ match end of string
So Regular expressions is a way to do pattern matching, in this case the pattern is 16/2/0/{n} where {n} is any number. So by doing this we can find only those items that match that pattern.
Then if you have duplicates, you can do array_unique() and easily remove those.
There are many ways to do this array_filter with a custom callback etc. But this is the most straightforward way (if you know Regex).

How can I put strings in array starting from 0 index

hello I have a string like this
"*HQ,6170929875,V1,185905,A,3127.3354,N,07307.6954,E,000.09,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185915,A,3127.3365,N,07307.6951,E,002.30,018,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185925,A,3127.3372,N,07307.6952,E,000.76,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185935,A,3127.3369,N,07307.6947,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185945,A,3127.3371,N,07307.6951,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185955,A,3127.3377,N,07307.6952,E,000.21,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190005,A,3127.3376,N,07307.6950,E,000.17,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190015,A,3127.3376,N,07307.6953,E,000.07,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190025,A,3127.3375,N,07307.6955,E,000.59,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190035,A,3127.3373,N,07307.6944,E,000.35,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190045,A,3127.3378,N,07307.6950,E,000.23,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190055,A,3127.3381,N,07307.6955,E,000.32,000,060718,FFFFB9FF,410,04,03104,32566#"
I want to put all these values in an array. so I did this
$array = explode("*",$str);
Now when i printed the array the data is
Array
(
[0] =>
[1] => HQ,6170929875,V1,185905,A,3127.3354,N,07307.6954,E,000.09,000,060718,FFFFB9FF,410,04,03104,32566#
[2] => HQ,6170929875,V1,185915,A,3127.3365,N,07307.6951,E,002.30,018,060718,FFFFB9FF,410,04,03104,32566#
[3] => HQ,6170929875,V1,185925,A,3127.3372,N,07307.6952,E,000.76,000,060718,FFFFB9FF,410,04,03104,32566#
[4] => HQ,6170929875,V1,185935,A,3127.3369,N,07307.6947,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#
[5] => HQ,6170929875,V1,185945,A,3127.3371,N,07307.6951,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#
[6] => HQ,6170929875,V1,185955,A,3127.3377,N,07307.6952,E,000.21,000,060718,FFFFB9FF,410,04,03104,32566#
[7] => HQ,6170929875,V1,190005,A,3127.3376,N,07307.6950,E,000.17,000,060718,FFFFB9FF,410,04,03104,32566#
[8] => HQ,6170929875,V1,190015,A,3127.3376,N,07307.6953,E,000.07,000,060718,FFFFB9FF,410,04,03104,32566#
[9] => HQ,6170929875,V1,190025,A,3127.3375,N,07307.6955,E,000.59,000,060718,FFFFB9FF,410,04,03104,32566#
[10] => HQ,6170929875,V1,190035,A,3127.3373,N,07307.6944,E,000.35,000,060718,FFFFB9FF,410,04,03104,32566#
[11] => HQ,6170929875,V1,190045,A,3127.3378,N,07307.6950,E,000.23,000,060718,FFFFB9FF,410,04,03104,32566#
[12] => HQ,6170929875,V1,190055,A,3127.3381,N,07307.6955,E,000.32,000,060718,FFFFB9FF,410,04,03104,32566#
)
0 index is empty. I want to start the array from 0 index. Please help. what I am doing wrong here
The first element of your array is blank because your string begins with *. To solve this simply do:
$str = "*HQ,6170929875,V1,185905,A,3127.3354,N,07307.6954,E,000.09,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185915,A,3127.3365,N,07307.6951,E,002.30,018,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185925,A,3127.3372,N,07307.6952,E,000.76,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185935,A,3127.3369,N,07307.6947,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185945,A,3127.3371,N,07307.6951,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185955,A,3127.3377,N,07307.6952,E,000.21,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190005,A,3127.3376,N,07307.6950,E,000.17,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190015,A,3127.3376,N,07307.6953,E,000.07,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190025,A,3127.3375,N,07307.6955,E,000.59,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190035,A,3127.3373,N,07307.6944,E,000.35,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190045,A,3127.3378,N,07307.6950,E,000.23,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190055,A,3127.3381,N,07307.6955,E,000.32,000,060718,FFFFB9FF,410,04,03104,32566#";
$arr = explode('*', $str);
array_shift($arr);
print_r($arr);
Which produces:
Array
(
[0] => HQ,6170929875,V1,185905,A,3127.3354,N,07307.6954,E,000.09,000,060718,FFFFB9FF,410,04,03104,32566#
[1] => HQ,6170929875,V1,185915,A,3127.3365,N,07307.6951,E,002.30,018,060718,FFFFB9FF,410,04,03104,32566#
[2] => HQ,6170929875,V1,185925,A,3127.3372,N,07307.6952,E,000.76,000,060718,FFFFB9FF,410,04,03104,32566#
[3] => HQ,6170929875,V1,185935,A,3127.3369,N,07307.6947,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#
[4] => HQ,6170929875,V1,185945,A,3127.3371,N,07307.6951,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#
[5] => HQ,6170929875,V1,185955,A,3127.3377,N,07307.6952,E,000.21,000,060718,FFFFB9FF,410,04,03104,32566#
[6] => HQ,6170929875,V1,190005,A,3127.3376,N,07307.6950,E,000.17,000,060718,FFFFB9FF,410,04,03104,32566#
[7] => HQ,6170929875,V1,190015,A,3127.3376,N,07307.6953,E,000.07,000,060718,FFFFB9FF,410,04,03104,32566#
[8] => HQ,6170929875,V1,190025,A,3127.3375,N,07307.6955,E,000.59,000,060718,FFFFB9FF,410,04,03104,32566#
[9] => HQ,6170929875,V1,190035,A,3127.3373,N,07307.6944,E,000.35,000,060718,FFFFB9FF,410,04,03104,32566#
[10] => HQ,6170929875,V1,190045,A,3127.3378,N,07307.6950,E,000.23,000,060718,FFFFB9FF,410,04,03104,32566#
[11] => HQ,6170929875,V1,190055,A,3127.3381,N,07307.6955,E,000.32,000,060718,FFFFB9FF,410,04,03104,32566#
)
You could pass it to array_filter to remove first child (index 0). It happen because you have * on first part of string. Exploding by * delimiter mean zero string on first value.
Something like:
$array = explode("*",$str);
$array = array_filter($array);
This is occurring simply because you have a "*" character at the start of the string
*HQ,6170929875,V1,185905,A,3127.3354,N,07307.6954,E,000.09,000,060718,FFFFB9FF,410,04,03104,32566#*....
If you always have that character at the start of the string, you will always have an empty index 0 in your resultant array - you need to either remove the first character before exploding the string or the first item of the array.
You might use a combination of array_filter to remove the empty values and array_values to reindex the array to start from 0:
$str = "*HQ,6170929875,V1,185905,A,3127.3354,N,07307.6954,E,000.09,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185915,A,3127.3365,N,07307.6951,E,002.30,018,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185925,A,3127.3372,N,07307.6952,E,000.76,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185935,A,3127.3369,N,07307.6947,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185945,A,3127.3371,N,07307.6951,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,185955,A,3127.3377,N,07307.6952,E,000.21,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190005,A,3127.3376,N,07307.6950,E,000.17,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190015,A,3127.3376,N,07307.6953,E,000.07,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190025,A,3127.3375,N,07307.6955,E,000.59,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190035,A,3127.3373,N,07307.6944,E,000.35,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190045,A,3127.3378,N,07307.6950,E,000.23,000,060718,FFFFB9FF,410,04,03104,32566#*HQ,6170929875,V1,190055,A,3127.3381,N,07307.6955,E,000.32,000,060718,FFFFB9FF,410,04,03104,32566#";
print_r(array_values(array_filter(explode("*", $str))));
Result:
Array
(
[0] => HQ,6170929875,V1,185905,A,3127.3354,N,07307.6954,E,000.09,000,060718,FFFFB9FF,410,04,03104,32566#
[1] => HQ,6170929875,V1,185915,A,3127.3365,N,07307.6951,E,002.30,018,060718,FFFFB9FF,410,04,03104,32566#
[2] => HQ,6170929875,V1,185925,A,3127.3372,N,07307.6952,E,000.76,000,060718,FFFFB9FF,410,04,03104,32566#
[3] => HQ,6170929875,V1,185935,A,3127.3369,N,07307.6947,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#
[4] => HQ,6170929875,V1,185945,A,3127.3371,N,07307.6951,E,000.27,000,060718,FFFFB9FF,410,04,03104,32566#
[5] => HQ,6170929875,V1,185955,A,3127.3377,N,07307.6952,E,000.21,000,060718,FFFFB9FF,410,04,03104,32566#
[6] => HQ,6170929875,V1,190005,A,3127.3376,N,07307.6950,E,000.17,000,060718,FFFFB9FF,410,04,03104,32566#
[7] => HQ,6170929875,V1,190015,A,3127.3376,N,07307.6953,E,000.07,000,060718,FFFFB9FF,410,04,03104,32566#
[8] => HQ,6170929875,V1,190025,A,3127.3375,N,07307.6955,E,000.59,000,060718,FFFFB9FF,410,04,03104,32566#
[9] => HQ,6170929875,V1,190035,A,3127.3373,N,07307.6944,E,000.35,000,060718,FFFFB9FF,410,04,03104,32566#
[10] => HQ,6170929875,V1,190045,A,3127.3378,N,07307.6950,E,000.23,000,060718,FFFFB9FF,410,04,03104,32566#
[11] => HQ,6170929875,V1,190055,A,3127.3381,N,07307.6955,E,000.32,000,060718,FFFFB9FF,410,04,03104,32566#
)

Reg Exp - preg_match_all reduce array result

This is my Reg Exp "[c]?[\d+|\D+]\s*". My input is this "c7=c4/c5*100" and the result is :
Array
(
[0] => Array
(
[0] => c7
[1] => =
[2] => c5
[3] => +
[4] => c3
[5] => *
[6] => 1
[7] => 0
[8] => 0
)
)
But what I want is:
Array
(
[0] => Array
(
[0] => c7
[1] => =
[2] => c5
[3] => +
[4] => c3
[5] => *
[6] => 100
)
)
I can't seem to get the last part working, I'm lost as what to do next - Can anyone help?
Thanks,
Paul
You specified a character class [\d+|\D+] which would match any of the specified characters. I think you meant using an or | with a grouping construct c?(?:\d+|\D+)\s* but in that case it would match c followed by either \d+ or \D so that would match the = sign right after it resulting in c= as a match and /c as a match.
Try matching an optional c c? followed by one or more digits or | match not a digit \D
c?\d+|\D
$re = '/c?\d+|\D/m';
$str = 'c7=c4/c5*100';
preg_match_all($re, $str, $matches);
print_r($matches);
That will result in:
Array
(
[0] => Array
(
[0] => c7
[1] => =
[2] => c4
[3] => /
[4] => c5
[5] => *
[6] => 100
)
)
Demo

How to match an optional subpattern in the middle or end of an url depending on the existence of a filename and extension

I am trying to preg_match a url consisting of a category slug, an optional subcategory slug and an option item slug.
It works in all cases, except for the 4th case.
$urls[0] = '/main_cat_slug';
$urls[1] = '/main_cat_slug/';
$urls[2] = '/main_cat_slug/sub_cat_slug';
$urls[3] = '/main_cat_slug/sub_cat_slug/';
$urls[4] = '/main_cat_slug/item.html';
$urls[5] = '/main_cat_slug/sub_cat_slug/item.html';
$regexp = array();
$regexp[] = '/(?:(?<category>[\w]+)/?)'; // Find the main category (is always available)
$regexp[] = '(?:(?<subcategory>[\w]+)/?)?'; // Find an optional sub-category, is not always available
$regexp[] = '(?:(?<item>[\w]+)\.html)?'; // Find an optional item, is not always available (don't catch the extension)
$regexp = implode('', $regexp);
foreach($urls as $index=>$url) {
preg_match("#{$regexp}#i", $url, $matches);
echo '<pre><h1>', $index, '</h1>';
echo $url, '<br />';
echo '<br />';
print_r($matches);
}
In the 4-th case, the category will be found, but the item is empty and the subcategory gets the value op "item".
Could someone help me out, so that the 4-th case will only get a category and an item?
This is the output for above code:
0
/main_cat_slug
Array
(
[0] => /main_cat_slug
[category] => main_cat_slug
[1] => main_cat_slug
)
1
/main_cat_slug/
Array
(
[0] => /main_cat_slug/
[category] => main_cat_slug
[1] => main_cat_slug
)
2
/main_cat_slug/sub_cat_slug
Array
(
[0] => /main_cat_slug/sub_cat_slug
[category] => main_cat_slug
[1] => main_cat_slug
[subcategory] => sub_cat_slug
[2] => sub_cat_slug
)
3
/main_cat_slug/sub_cat_slug/
Array
(
[0] => /main_cat_slug/sub_cat_slug/
[category] => main_cat_slug
[1] => main_cat_slug
[subcategory] => sub_cat_slug
[2] => sub_cat_slug
)
4
/main_cat_slug/item.html
Array
(
[0] => /main_cat_slug/item
[category] => main_cat_slug
[1] => main_cat_slug
[subcategory] => item
[2] => item
)
5
/main_cat_slug/sub_cat_slug/item.html
Array
(
[0] => /main_cat_slug/sub_cat_slug/item.html
[category] => main_cat_slug
[1] => main_cat_slug
[subcategory] => sub_cat_slug
[2] => sub_cat_slug
[item] => item
[3] => item
)
Kind regards!
Patrick
Description
This regex will pickout the three types of data, using the following rules:
The / is always the first character in the string
The Main_Cat is always first, it follows the first / and continues until the next /
If the first string ends in .html/ then this is a Main_Cat
if the first string ends in .html followed by the end of the string, then this is an item
The Sub_Cat is always second, it follows the second / and continues until the next /
If the second string ends in .html/ then this is a Sub_Cat
if the second string ends in .html followed by the end of the string, then this is an item
The Item type always has an .html suffix
There will never be a / after the Item
the Item type will always be the last field
^\/(?:(?<Main_Cat>(?![^\/\r\n]*\.html\s*$)[^\/\r\n]*)\/)?(?:(?<Sub_Cat>(?![^\/\r\n]*\.html\s*$)[^\/\r\n]*)\/)?(?:(?<Item>[^\/\r\n]*?)(?:\.html|$))?
If you're using this expression against individual strings then you can remove the new line characters \r\n. The resulting expression would look like: ^\/(?<Main_Cat>[^\/]*)(?:(?:\/(?![^\/]*\.html)(?<Sub_Cat>[^\/]*))?(?:\/(?<Item>[^\/]*)\.html)?)?.*?$ follows the same rules above. Note the end of line $ forces the test to match your entire string
PHP Code Example:
Source String
/category0.html/subcat/item.html
/item1.html
/category2.html/subcat2.html/item2.html
/category3.html/subcat3.html/
/category4.html/item4.html
/main_cat_slug5.html/
/main_cat_slug6/item6
/main_cat_slug7/sub_cat_slug7.html/
/main_cat_slug8/item8.html
/main_cat_slug9/sub_cat_slug9/item9.html
Code
<?php
$sourcestring="your source string";
preg_match_all('/^\/(?:(?<Main_Cat>(?![^\/\r\n]*\.html\s*$)[^\/\r\n]*)\/)?(?:(?<Sub_Cat>(?![^\/\r\n]*\.html\s*$)[^\/\r\n]*)\/)?(?:(?<Item>[^\/\r\n]*?)(?:\.html|$))?/imx',$sourcestring,$matches);
echo "<pre>".print_r($matches,true);
?>
Matches
$matches Array:
(
[0] => Array
(
[0] => /category0.html/subcat/item.html
[1] => /item1.html
[2] => /category2.html/subcat2.html/item2.html
[3] => /category3.html/subcat3.html
[4] => /category4.html/item4.html
[5] => /main_cat_slug5.html
[6] => /main_cat_slug6
[7] => /main_cat_slug7/sub_cat_slug7.html
[8] => /main_cat_slug8/item8.html
[9] => /main_cat_slug9/sub_cat_slug9/item9.html
)
[Main_Cat] => Array
(
[0] => category0.html
[1] =>
[2] => category2.html
[3] => category3.html
[4] => category4.html
[5] => main_cat_slug5.html
[6] => main_cat_slug6
[7] => main_cat_slug7
[8] => main_cat_slug8
[9] => main_cat_slug9
)
[Sub_Cat] => Array
(
[0] => subcat
[1] =>
[2] => subcat2.html
[3] => subcat3.html
[4] =>
[5] =>
[6] =>
[7] => sub_cat_slug7.html
[8] =>
[9] => sub_cat_slug9
)
[Item] => Array
(
[0] => item
[1] => item1
[2] => item2
[3] =>
[4] => item4
[5] =>
[6] =>
[7] =>
[8] => item8
[9] => item9
)
)
You can try this:
preg_match('~/(?<main_cat>[^/\s]++/?+)(?<sub_cat>[^/\s]++/?+)?'
. '(?>(?<filename>\S+?)\.html)?~', $url, $match);
print_r($match);
Note that you can access easily to the different parts with the named captures (useful to test if there is a subpattern or not.).

preg_split with regex giving incorrect output

I'm using preg_split to an string, but I'm not getting desired output. For example
$string = 'Tachycardia limit_from:1900-01-01 limit_to:2027-08-29 numresults:10 sort:publication-date direction:descending facet-on-toc-section-id:Case Reports';
$vals = preg_split("/(\w*\d?):/", $string, NULL, PREG_SPLIT_DELIM_CAPTURE);
is generating output
Array
(
[0] => Tachycardia
[1] => limit_from
[2] => 1900-01-01
[3] => limit_to
[4] => 2027-08-29
[5] => numresults
[6] => 10
[7] => sort
[8] => publication-date
[9] => direction
[10] => descending facet-on-toc-section-
[11] => id
[12] => Case Reports
)
Which is wrong, desire output it
Array
(
[0] => Tachycardia
[1] => limit_from
[2] => 1900-01-01
[3] => limit_to
[4] => 2027-08-29
[5] => numresults
[6] => 10
[7] => sort
[8] => publication-date
[9] => direction
[10] => descending
[11] => facet-on-toc-section-id
[12] => Case Reports
)
There something wrong with regex, but I'm not able to fix it.
I would use
$vals = preg_split("/(\S+):/", $string, NULL, PREG_SPLIT_DELIM_CAPTURE);
Output is exactly like you want
It's because the \w class does not include the character -, so i would expand the \w with that too:
/((?:\w|-)*\d?):/
Try this regex instead to include '-' or other characters in your splitting pattern: http://regexr.com?32qgs
((?:[\w\-])*\d?):

Categories