how to parse this: char(x)? - php

I use YAML to get MySQL schema and i need to parse only these kind of strings CHAR(60) or VARCHAR(90) etc..
Parsing result would be like this:
array('CHAR', 60);
array('VARCHAR', 90);

The following regex will do it. If these don't occur one per line, you should also add the \b boundaries after the opening slash and before the closing one.
$s = "VARCHAR(90)";
$matches = array();
preg_match("/([A-Z]+)\(([0-9]+)\)/", $s, $matches);
// Then use the matched values into your array.
array($matches[1], $matches[2]);
EDIT: Had the $matches array keys wrong the first time. Should be 1 & 2, not 0 & 1.

Related

PHP - preg_replace how to add an extra "]" and an extra "["

Is there any way to do this with preg_replace or other php code?
I have a string that looks like this:
[[10],[11],[2],[3],[5],[1],[10],[15],[20],[21],[14],[16],[17],[6],[9],[4]]
I want to display like this:
[[10,11],[2,3],[5,1],[10,15],[20,21],[14,16],[17,6],[9,4]]
So I replaced the "],[" part with str_replace
$xy1 = str_replace('],[', ',', $xy1);
And now looks like this:
[[10,11,2,3,5,1,10,15,20,21,14,16,17,6,9,4]]
But I need to add an extra "]" after every second number and an extra [ after every second comma ex.:
[[10,11],[2,3],[5,1]
A couple of possibilities:
The string is valid JSON, whether it was intended to be or not, so you can decode it, chunk the resulting array and re-encode it.
$result1 = json_encode(array_chunk(array_column(json_decode($string),0),2));
If you are producing the string in your previous code via json_encode it would be much better to just use array_chunk at that time, but if it's coming from some other source you obviously can't do that.
For this specific string, it may be less cumbersome to pair the numbers with a regex.
$result2 = preg_replace('/(\d+)\D+(\d+)/', '$1,$2', $string);
Or a combination of both ways, extract all the numbers and then chunk and encode.
preg_match_all('/\d+/', $string, $numbers);
$result3 = json_encode(array_chunk($numbers[0], 2), JSON_NUMERIC_CHECK);
This might help, extract the nested array values and then group them by pairs.
$newArray = array_chunk( array_column( $array, 0 ), 2 );

How to get equal parts of multiple strings/array?

I have the following point: a xls file contains one column with codes. The codes have a prefix and a unique code like this:
- VIP-AX757
- VIP-QBHE6
- CODE-IUEF7
- CODE-QDGF3
- VIP-KJQFB
- ...
How can I get equal parts of strings or an array? perfect would be if I get an array like this:
- $result[VIP] = 3;
- $result[CODE] = 2;
An array with the found prefix and the sum of cells with that prefix. But the result is not so important at the moment.
I couldn't find a soloution how to get equal parts of two strings: how to compare this "VIP-AX757" and "VIP-QBHE6" and get a result that says: "VIP-" is the same prefix/part in this two strings?
Hope someone has an idea.
thx!
-drum roll- Time for a one-liner!
$result = array_count_values(array_map(function($v) {list($a) = explode("-",$v); return $a;},$input));
(Assumes $input is your array of codes)
If you are using PHP 5.4 or newer (you should be), then:
$result = array_count_values(array_map(function($v) {return explode("-",$v)[0];},$input));
Tested in PHP CLI:
If the prefix is always followed by a '-' then you can do something like this:-
foreach ($codes as $code) {
$tmp = explode("-",$code);
$result[$tmp[0]] += 1;
}
print_r($result);
Depends on the variability of the data, but something like:
preg_match_all('/^([^-]+)/m', $string, $matches);
$result = array_count_values($matches[1]);
print_r($result);
If you don't know that there is an - after the prefix but the prefix is always letters then:
preg_match_all('/^([A-Z]+)/im', $string, $matches);
$result = array_count_values($matches[1]);
Otherwise you'll have to define exactly what the prefix can contain if it's not the delimiter.
Since you stated via comment to Niet that you don't have a reliable delimiter, then we can only write a pattern that identifies your targeted substrings based on their location in each line.
I recommend preg_match_all() with no capture group, a start of the line anchor, and a multi-line pattern modifier (m).
I've written a preg_split() alternative, but the pattern is a little "clunkier" because of the way I'm handling the line returns.
Code: (Demo)
$string = 'VIP-AX757
VIP-QBHE6
CODE-IUEF7
CODE-QDGF3
VIP-KJQFB';
var_export(array_count_values(preg_match_all('~^[A-Z]+~m', $string, $out) ? $out[0] : []));
echo "\n\n";
var_export(array_count_values(preg_split('~[^A-Z][^\r\n]+\R?~', $string, -1, PREG_SPLIT_NO_EMPTY)));
Output:
array (
'VIP' => 3,
'CODE' => 2,
)
array (
'VIP' => 3,
'CODE' => 2,
)

Split string into array with pattern

I send from flex an array to my php script.
String to split is like [F1, 3, true][Urg, 4, false]
I'd to use those information to update record into mySql database.
For example [F1, 3, true] is a record like this [Name, Id, Visible].
But I don't how to split to use information.
Thanks for helping
You can remove the brackets:
$txt = substr($txt, 1, -1);
And explode:
$array = explode(',', $txt)
If you really insist on that format you could try preg_match.
$string = '[F1, 3, true][Urg, 4, false][asd, 1337, TrUe]';
preg_match_all('/\[(\w+),\s*?(\d+),\s*?(true|false)\]/i', $string, $matches, PREG_SET_ORDER);
With this you will get an two-dimensional array, each element in the array is an array. The first element in each array is the matches data row, the following elements are the parsed data.
The elements can be separated by as many whitespace characters as you want, the case of the boolean value does not matter.
I hope there are no commas or square brackets in your data strings - that could make this impossible! But assuming there are none of those:
preg_match_all('/\[([^\]]*)\]/', $text, $matches);
return array_map(function($match) {
return array_map('trim', explode(',', $match));
}, $matches[1]);
(That uses a closure, which is only supported in PHP 5.3 and later; if you are on an older version, you can change it to a foreach loop pretty easily.)

PHP : Get a number between 2 strings

I have this string:
a:3:{i:0;i:2;i:1;i:3;i:2;i:4;}
I want to get number between "a:" and ":{" that is "3".
I try to user substr and strpos but no success.
I'm newbie in regex , write this :
preg_match('/a:(.+?):{/', $v);
But its return me 1.
Thanks for any tips.
preg_match returns the number of matches, in your case 1 match.
To get the matches themselves, use the third parameter:
$matches = array();
preg_match(/'a:(\d+?):{/', $v, $matches);
That said, I think the string looks like a serialized array which you could deserialize with unserialize and then use count on the actual array (i.e. $a = count(unserialize($v));). Be careful with userprovided serialized strings though …
If you know that a: is always at the beginning of the string, the easiest way is:
$array = explode( ':', $string, 3 );
$number = $array[1];
You can use sscanfDocs to obtain the number from the string:
# Input:
$str = 'a:3:{i:0;i:2;i:1;i:3;i:2;i:4;}';
# Code:
sscanf($str, 'a:%d:', $number);
# Output:
echo $number; # 3
This is often more simple than using preg_match when you'd like to obtain a specific value from a string that follows a pattern.
preg_match() returns the number of times it finds a match, that's why. you need to add a third param. $matches in which it will store the matches.
You were not too far away with strpos() and substr()
$pos_start = strpos($str,'a:')+2;
$pos_end = strpos($str,':{')-2;
$result = substr($str,$pos_start,$pos_end);
preg_match only checks for appearance, it doesn't return any string.

Parse text and populate associative array from two substrings per line

Given a large string of text, I want to search for the following patterns:
#key: value
So an example is:
some crazy text
more nonesense
#first: first-value;
yet even more non-sense
#second: second-value;
finally more non-sense
The output should be:
array("first" => "first-value", "second" => "second-value");
<?php
$string = 'some crazy text
more nonesense
#first: first-value;
yet even more non-sense
#second: second-value;
finally more non-sense';
preg_match_all('##(.*?): (.*?);#is', $string, $matches);
$count = count($matches[0]);
for($i = 0; $i < $count; $i++)
{
$return[$matches[1][$i]] = $matches[2][$i];
}
print_r($return);
?>
Link http://ideone.com/fki3U
Array (
[first] => first-value
[second] => second-value )
Tested in PHP 5.3:
// set-up test string and final array
$myString = "#test1: test1;#test2: test2;";
$myArr = array();
// do the matching
preg_match_all('/#([^\:]+)\:([^;]+);/', $myString, $matches);
// put elements of $matches in array here
$actualMatches = count($matches) - 1;
for ($i=0; $i<$actualMatches; $i++) {
$myArr[$matches[1][$i]] = $matches[2][$i];
}
print_r($myArr);
The reasoning behind this is this:
The regex is creating two capture groups. One capture group is the key, the
other the data for that key. The capture groups are the portions of the regex
inside left and right bananas, i.e., (...).
$actualMatches just adjusts for the fact that preg_match_all returns an
extra element containing all matches lumped together.
Demo.
Match whole qualifying lines starting with # and ending with ;.
Capture the substring that does not contain any colons as the first group and capture the substring between the space after the colon and the semicolon at the end of the line.
By using the any character dot in the second capture group, the substring may contain a semicolon without damaging any extracted data.
Call array_combine() to form key-value relationships between the two capture groups.
Code: (Demo)
preg_match_all(
'/^#([^:]+): (.+);$/m',
$text,
$m
);
var_export(array_combine($m[1], $m[2]));
Output:
array (
'first' => 'first-value',
'second' => 'second-value',
)
You can try looping the string line by line (explode and foreach) and check if the line starts with an # (substr) if it has, explode the line by :.
http://php.net/manual/en/function.explode.php
http://nl.php.net/manual/en/control-structures.foreach.php
http://nl.php.net/manual/en/function.substr.php
Depending on what your input string looks like, you might be able to simply use parse_ini_string, or make some small changes to the string then use the function.

Categories