preg_match correct regular expression - php

Since hours i try to find the correct regular expression. Let's say i have this:
$string = 'a=a.split("")';
and
$string = 'a=Ik(a,66)';
What i want to get as output is:
[1] => a
[2] => a
[3] => split
[4] => ""
and for the second one:
[1] => a
[2] => IK
[3] => a,66
I tried:
preg_match('#(.+)=(.+).(.+)[(](.+)[)]#', $string, $matches);
but this outputs:
Array
(
[0] => a=a.split("")
[1] => a
[2] => a.spl
[3] => t
[4] => ""
)
Why do i want this? I want to convert some javascript to PHP. For example:
function Hk(a) {
a = a.split("");
a = a.slice(1);
a = a.reverse();
a = Ik(a, 66);
a = a.slice(2);
a = a.reverse();
a = Ik(a, 12);
return a.join("")
}
function Ik(a, b) {
var c = a[0];
a[0] = a[b % a.length];
a[b] = c;
return a
}
# Edit: What i want is to convert it to PHP code and ouput it. I do not want to execute it.
For example the above javascript code should became something like this:
First function:
$a = str_split($a);
$a = array_slice($a, 1);
$a = array_reverse($a);
$a = self::Ik($a,66);
$a = array_slice($a, 2);
$a = array_reverse($a);
$a = self::Ik($a,12);
return implode("", $a);
second function:
$c = $a[0];
$a[0] = $a[$b%count($a)];
$a[$b] = $c;
return $a;
The function part itself is not imporant. I need only the logic in the function itself.

You might want to consider preg_split:
$arr = preg_split('/[=()]/', 'a=a.split("")', -1, PREG_SPLIT_NO_EMPTY);
Array
(
[0] => a
[1] => a.split
[2] => ""
)
$arr = preg_split('/[=()]/', 'a=Ik(a,66)', -1, PREG_SPLIT_NO_EMPTY);
Array
(
[0] => a
[1] => Ik
[2] => a,66
)

With php PCRE this should work for both patterns, even if you have different array elements filled, depending which pattern matches. I guess you can figure it our with testing the elements for nil etc.
This is done with an assertion and lookahead (do we have a dot, which results in one element more):
([^=]+)=(?(?=.+\.)([^.]+)\.([^.]+)|([^.]+))\((.+)\)
This is what comes up:
(
[0] => Array
(
[0] => a=Ik(a,66)
)
[1] => Array
(
[0] => a
)
[2] => Array
(
[0] =>
)
[3] => Array
(
[0] =>
)
[4] => Array
(
[0] => Ik
)
[5] => Array
(
[0] => a,66
)
)
and this one:
(
[0] => Array
(
[0] => a=a.split("")
)
[1] => Array
(
[0] => a
)
[2] => Array
(
[0] => a
)
[3] => Array
(
[0] => split
)
[4] => Array
(
[0] =>
)
[5] => Array
(
[0] => ""
)
)
Hope this is of help ;)

Related

Split array base on result of checking element

I have an array in PHP as below:
`
Array (
[0] => Array
(
[0] => Some text
[1] => 6230.C3
)
[1] => Array
(
[0] => Some text
[1] => 6230.C3
)
[2] => Array
(
[0] =>
[1] =>
)
[3] => Array
(
[0] => Some text
[1] =>
)
[4] => Array
(
[0] => Some text
[1] =>
)
[5] => Array
(
[0] => Some text
[1] =>
)
[6] => Array
(
[0] =>
[1] =>
)
[7] => Array
(
[0] => Some text
[1] =>
)
[8] => Array
(
[0] => Some text
[1] =>
)
)
`
Array[2] and Array[6] are empty arrays. Please help me split my array to three arrays array1, array2, array3 as below (split at position of Array[2] and Array[6]).
array1 = [ Array[0], Array[1] ]
array2 = [ Array[3], Array[4], Array[5] ]
Aarray3 = [ Array[7], Array[8] ]
Thank you for your help.
This is a little more flexible than your original question because it is not limited to exactly 3 arrays as separate variables. The result of the following would be an multidimensional array, split in the way that you want but for an unlimited number of splits. I can rework it if necessary to fit exactly 3 variables if that is really what your input will always be.
<?php
$final = array();
$counter = 0;
$outerEmpty = false;
foreach($originalArray as $outer) {
$innerEmpty = true;
foreach($outer as $inner) {
if (!empty($inner)) {
$innerEmpty = false;
break;
}
}
if (!$innerEmpty)
$final[$counter][] = $outer;
else
$counter++;
}

extracting data from multidimensional array via PHP and store in text file

I would like to extract data from the following JSON arrays, to a variable that i would like to use to create a text file
Array
(
[0] => Array
(
[0] => 0
[1] =>
)
[1] => Array
(
[0] => 0
[1] => 123:
)
[2] => Array
(
[0] => 0
[1] => TICKET
)
[3] => Array
(
[0] => 0
[1] => ------------------------------------------------
)
[4] => Array
(
[0] => 1
[1] => user 1
)
[5] => Array
(
[0] => 1
[1] => info x
)
[6] => Array
(
[0] => 0
[1] => ------------------------------------------------
)
[7] => Array
(
[0] => 0
[1] => TEXT 1
)
[8] => Array
(
[0] => 0
[1] => TEXT 2
)
[9] => Array
(
[0] => 0
[1] => TEXT 4
)
[10] => Array
(
[0] => 1
[1] => TEXT 4
)
[11] => Array
(
[0] => 0
[1] => TEXT 5
)
[12] => Array
(
[0] => 0
[1] => TEXT 6
)
[13] => Array
(
[0] => 0
[1] => TEXT 7
)
[14] => Array
(
[0] => 0
[1] => TEXT 8
)
[15] => Array
(
[0] => 0
[1] => TEXT 9
)
)
I use the following PHP, but only the array 15 value is returned in my text file.
$ticket = file_get_contents('php://input');
$ticket_output = json_decode($ticket,true);
$ticket_output_def = $ticket_output['ticket'];
$ticket_output_txt = print_r($ticket_output_def,true);
foreach ($ticket_output_def as $array){
$array0 = $array[0];
$array1 = $array[1];
$text = $array0 . $array1;
}
$filename = "output.txt";
file_put_contents($filename, $text);
Well that's normal since you reset $text at every loop iteration!
Maybe try this :
$ticket = file_get_contents('php://input');
$ticket_output = json_decode($ticket,true);
$ticket_output_def = $ticket_output['ticket'];
$ticket_output_txt = print_r($ticket_output_def,true);
$text = "";
foreach ($ticket_output_def as $array){
$array0 = $array[0];
$array1 = $array[1];
$text .= $array0 . $array1;
}
$filename = "output.txt";
file_put_contents($filename, $text);
You are resetting the value of $text in each iteration as #zoubida13 said. As the counter increases, text value is changed to concatenation of elements corresponding to that counter. You can try the method provided by #zoubida13, or you can also use FILE_APPEND as third parameter inside file_put_contents and the code will go like this
`
$ticket = file_get_contents('php://input');
$ticket_output = json_decode($ticket,true);
$ticket_output_def = $ticket_output['ticket'];
$ticket_output_txt = print_r($ticket_output_def,true);
$filename = "output.txt";
foreach ($ticket_output_def as $array) {
$array0 = $array[0];
$array1 = $array[1];
$text = $array0 . $array1;
file_put_contents($filename, $text,FILE_APPEND);
}
`
BUT, this will be an inefficient method I reckon, as it will try to write to the file each time. Its better to concat the text in each iteration and write it after the loop has executed.
I found the solution. You have to use the PHP_EOL; Predefined Constant
$text = $text . $array0 . $array1 . PHP_EOL;

preg_match_all and umlets

I am using preg_match_all to filter out strings
The string which I have supplied in preg_match_all is
$text = "Friedric'h Wöhler"
after that I use
preg_match_all('/(\"[^"]+\"|[\\p{L}\\p{N}\\*\\-\\.\\?]+)/', $text, $arr, PREG_PATTERN_ORDER);
and the result i get when I print $arr is
Array
(
[0] => Array
(
[0] => friedric
[1] => h
[2] => w
[3] => ouml
[4] => hler
)
[1] => Array
(
[0] => friedric
[1] => h
[2] => w
[3] => ouml
[4] => hler
)
)
Somehow the ö character is replaced by ouml which I am not really sure how to figure this out
I am expecting following result
Array
(
[0] => Array
(
[0] => Friedric'h
[1] => Wöhler
)
)
Per nhahtdh's comment:
$text = "Friedric'h Wöhler";
preg_match_all('/"[^"]+"|[\p{L}\p{N}*.?\\\'-]+/u', $text, $arr, PREG_PATTERN_ORDER);
echo "<pre>";
print_r($arr);
echo "</pre>";
Gives
Array
(
[0] => Array
(
[0] => Friedric'h
[1] => Wöhler
)
)
If you think preg_match_all() is messy, you could take a look at pattern():
$p = '"[^"]+"|[\p{L}\p{N}*.?\\\'-]+'; // automatic delimiters
$text = "Friedric'h Wöhler";
$result = pattern($p)->match($text)->all();

Parsing attributes in PHP using regular expressions

Consider that i have the string,
$string = 'tag2 display="users" limit="5"';
Using the preg_match_all function, i need to get the output
Required o/p
Array
(
[0] => Array
(
[0] => tag2
[1] => tag2
[2] =>
)
[1] => Array
(
[0] => display="users"
[1] => display
[2] => users
)
[2] => Array
(
[0] => limit="5"
[1] => limit
[2] => 5
)
)
I tried using this pattern '/([^=\s]+)="([^"]+)"/' but it is not recognizing the parameter with no value (in this case tag2) Instead it gives the output
What I am getting
Array
(
[0] => Array
(
[0] => display="users"
[1] => display
[2] => users
)
[1] => Array
(
[0] => limit="5"
[1] => limit
[2] => 5
)
)
What will be the pattern for getting the required output ?
EDIT 1: I also need to get the attributes which are not wrapped with quotes ex: attr=val. Sorry for not mentioning before.
Try this:
<?php
$string = 'tag2 display="users" limit="5"';
preg_match_all('/([^=\s]+)(="([^"]+)")?/', $string, $res);
foreach ($res[0] as $r => $v) {
$o[] = array($res[0][$r], $res[1][$r], $res[3][$r]);
}
print_r($o);
?>
It outputs me:
Array
(
[0] => Array
(
[0] => tag2
[1] => tag2
[2] =>
)
[1] => Array
(
[0] => display="users"
[1] => display
[2] => users
)
[2] => Array
(
[0] => limit="5"
[1] => limit
[2] => 5
)
)
I think it's not fully possible to give you with one call what you're looking for, but this is pretty close:
$string = 'tag2 display="users" limit=5';
preg_match_all('/([^=\s]+)(?:="?([^"]+)"?|())?/', $string, $res, PREG_SET_ORDER);
print_r($res);
Output:
Array
(
[0] => Array
(
[0] => tag2
[1] => tag2
[2] =>
[3] =>
)
[1] => Array
(
[0] => display="users"
[1] => display
[2] => users
)
[2] => Array
(
[0] => limit=5
[1] => limit
[2] => 5
)
)
As you can see, the first element has no value, I tried to work around that and offer an empty match now. So this builds the array you were asking for, but has an additional entry on the empty attribute.
However the main point is the PREG_SET_ORDER flag of preg_match_all. Maybe you can live with this output already.
Maybe you're interested in this litte snippet that parses all sorts of attribute styles. <div class="hello" id=foobar style='display:none'> is valid html(5), not pretty, I know…
<?php
$string = '<tag2 display="users" limit="5">';
$attributes = array();
$pattern = "/\s+(?<name>[a-z0-9-]+)=(((?<quotes>['\"])(?<value>.*?)\k<quotes>)|(?<value2>[^'\" ]+))/i";
preg_match_all($pattern, $source, $matches, PREG_SET_ORDER);
foreach ($matches as $match) {
$attributes[$match['name']] = $match['value'] ?: $match['value2'];
}
var_dump($attributes);
will give you
$attributes = array(
'display' => 'users',
'limit' => '5',
);

extract values from a query regex

I need to extract the values ​​of a condition (WHERE) and did a regex, but I can not get the values ​​correctly.
//Patherns
$regex = "/([a-zA-Z_]+)\s([\<\=\>\s]{0,4})\s+(\".*\")/";
//values ​​to be extracted
$string = 'idCidade >= "bla" OR idEstado="2" and idPais="3"';
//regex function
preg_match_all(
$regex,
$string,
$output
);
//displays the result
echo '<pre>';print_r($output);
//incorrect output
Array
(
[0] => Array
(
[0] => idCidade >= "bla" OR idEstado="2" and idPais="3"
)
[1] => Array
(
[0] => idCidade
)
[2] => Array
(
[0] => >=
)
[3] => Array
(
[0] => "bla" OR idEstado="2" and idPais="3"
)
)
I need the regular expression to export the values ​​to an array like this;
//correct output
Array
(
[0] => Array
(
[0] => idCidade >= "bla" OR idEstado="2" and idPais="3"
)
[1] => Array
(
[0] => idCidade
[1] => idEstado
[2] => idPais
)
[2] => Array
(
[0] => >=
[1] => =
[2] => =
)
[3] => Array
(
[0] => "bla"
[1] => "2"
[2] => "3"
)
[4] => Array
(
[0] => "OR"
[1] => "AND"
[2] => ""
)
)
Your mistake was probably the .* which matches too much. You'd need to make it "ungreedy" with appending a question mark: .*?
I would however suggest this regex:
'/(OR|AND)?\s*(\w+)\s*([<=>!]+)\s*("[^"]*"|\'[^\']*\'|\d+)/i'
This matches the boolean connector first and optionally, so that you get:
[1] => Array
(
[0] =>
[1] => OR
[2] => and
)
[2] => Array
(
[0] => idCidade
[1] => idEstado
[2] => idPais
)
[3] => Array
(
[0] => >=
[1] => =
[2] => =
)
[4] => Array
(
[0] => "bla"
[1] => "2"
[2] => "3"
)
I've also made it work for SQL-compliant strings and decimals. But this is only borderline a job for regex. A real parser would be advisable. (Though I don't know your use case.)
Try this. This outputs the exact result you need.
<?php //Patherns
$regex = '/([a-zA-Z_]+)\s*([>=<]*)\s*"([^"]*)"\s*(or|and)*/i';
//values to be extracted
$string = 'idCidade >= "bla" OR idEstado="2" and idPais="3"';
//regex function
preg_match_all(
$regex,
$string,
$output
);
//displays the result
echo '<pre>';print_r($output);

Categories