I want to extract data from a string - php

I have a string like the one below. I want to be able to extract the data and put it into variables. I would have used a function that focuses on a specifically formatted string but then it would create problems if the string is slightly different.
$str ="Surname : Lorem Creme
Name : Doe
Bank name :P.O.S
Account no:50345343
EC no:0000000K
ID no :85-000000 Q 85
DOB : 01-06-34
Employer name:min of education
Employeer Number: Borera pry 066 Mutawatawa
Client Physical Address: 45 New Lipore";
function ge($string, $start, $end){
$string = ' '. $string;
$ini =strpos($string, $start);
if ($ini == 0) return '';
$ini += strlen($start);
$len = strpos($string, $end, $ini) - $ini;
$den =substr($string, $ini, $len);
return substr($den, 0, -4);
}
if (isset($_POST['insert'])){
$real = $str;
$guru = preg_replace('/\s+/', '', $real);
$rem = str_replace(':', '', $guru);
$ren = str_replace('-', '', $rem);
$surname = ge($ren, "Surname", "Name");
$firstname =ge($ren, "Name", "Bankname");
$account_number = ge($ren, "Accountno", "ECno");
$Ec = ge($ren, "ECno", "IDno");
$id_num = ge($ren, 'IDno', "DOB");
$dob = ge($ren, "DOB", "Employername");
// Employer name:min of education
echo "First name: $firstname <br> Last name: $surname <br>";
echo "Bank : $bank_name <br>";
echo "ID Number : $id_num <br>";
echo "Account Number : $account_number <br>";
echo "DOB : $dob <br>";
echo "EC Number : $nex_ofk";
}
`

You can either you explode() twice with new line and then with : or you simple regex with preg_match_all
$str ="Surname : Lorem Creme
Name : Doe
Bank name :P.O.S
Account no:50345343
EC no:0000000K
ID no :85-000000 Q 85
DOB : 01-06-34
Employer name:min of education
Employeer Number: Borera pry 066 Mutawatawa
Client Physical Address: 45 New Lipore";
preg_match_all("#^\s*(.*?):\s*(.*?)\s*$#mx", $str, $matches);
var_dump(array_combine($matches[1], $matches[2]));
Output:
array(10) {
["Surname "]=>
string(11) "Lorem Creme"
["Name "]=>
string(3) "Doe"
["Bank name "]=>
string(5) "P.O.S"
["Account no"]=>
string(8) "50345343"
["EC no"]=>
string(8) "0000000K"
["ID no "]=>
string(14) "85-000000 Q 85"
["DOB "]=>
string(8) "01-06-34"
["Employer name"]=>
string(16) "min of education"
["Employeer Number"]=>
string(25) "Borera pry 066 Mutawatawa"
["Client Physical Address"]=>
string(13) "45 New Lipore"
}
The magic is in regex #^\s*(.*?):\s*(.*?)\s*$#mx you can find explanation here
array_combine() gets the values from 2 groups and combine them together to get one array.
preg_match_all applies regex to given string and return the output in
$matches array

Simplest way is with two explode calls:
<?php
$str ="Surname : Lorem Creme
Name : Doe
Bank name :P.O.S
Account no:50345343
EC no:0000000K
ID no :85-000000 Q 85
DOB : 01-06-34
Employer name:min of education
Employeer Number: Borera pry 066 Mutawatawa
Client Physical Address: 45 New Lipore";
//Split string into separate lines
$lines = explode(PHP_EOL, $str);
$result = array();
foreach($lines as $ln){
//Use explode to get the pieces left and right of the ':'
list($key, $val) = explode(':', $ln);
//Put that in a new array; use trim to get rid of 'presumably' unwanted whitespace
$result[trim($key)] = trim($val);
}
var_dump($result);
?>
You can also do this in one line with a regular expression, but this is probably simpler to understand.

Use php explode() function:
http://php.net/manual/en/function.explode.php
First do explode by new row to get rows (check on PHP_EOL constant here: http://php.net/manual/en/reserved.constants.php) and loop through them.
Then use another explode() call to explode by ":" sign to get field name and field value.
Use trim() function to remove space characters if they bother you.
$rows = explode(PHP_EOL, $str);
foreach ($rows as $row){
$rowParts = explode(':', $row);
$fieldName = trim($rowParts[0]);
$fieldValue = trim($rowParts[1]);
}
Should be something like that (I didn't test the code).

Depending on what your delimiter is, you can use explode()
In this case it looks like your delimiter is "\r\n". The explode would look like this:
$result = explode("\r\n", $str);
Afterwards you can explode on ":" as well, to get at key value result

Related

php indexed array manipulation and filtering

I have an array manipulation/situation that I cannot figure out. In a nutshell:
Get a string such as:
$testString = 'John doe 123 Main st 77555';
I am trying to get things split up to be 3 main parts such as:
$fname = 'John';
$lname = 'doe';
$address = '123 Main st 77555';
Currently I am exploding the array as such:
$splitTestString = explode(" ", $testString");
which gives me the string inside an array.
I've tried a for loop to go through the exploded string:
for($i = 0; $i <= count($splitTestString); $i++) {
$fname = $splitTestString[0];
$lname = $splitTestString[1];
if(is_numeric($splitTestString[2])) { //take into account 2 last names
$newAddress = $splitTestString[2];
} else {
$lname .= ' '.$splitTestString[2];
}
}
But I am not sure how to get the address after the initial numbers all into its own variable. Another string example:
$testString = 'John doe smith 123 main st 77555';
$fname = 'John';
$lname = 'doe smith';
$newAddress = '123 main st 77555';
The user would be instructed to enter the information in the above format of first name, last name, address and zip code.
This is my first question out of all the searches I've done on here and please let me know if I've not followed the rules properly. I'm just at my wits end on this problem and cannot seem to find a solution to this situation. Thanks in advance!
You don't need to do everything in a single loop, you should come up with a process for populating the name variables until you hit a word that starts with a number (is this really a safe assumption though?), then simply join the remainder into the address.
If possible, you should go back to the drawing board and provide a way for the user to provide the information in separate fields.
$testString = 'John doe smith villalobos garcia navarro 123 Main st 77555';
$parts = explode(' ', $testString);
// Don't assume we will always have a first or last name, there could be only an address
$fname = '';
// Set up a buffer for the last name words
$lnameBuffer = [];
// Process input buffer until we hit a part that begins with a number
while(!is_numeric(substr($parts[0], 0, 1)))
{
// Shift the next word off of the buffer
$currPart = array_shift($parts);
/*
* If we don't have a first name yet, set it
* Otherwise, append the word to the last name buffer
*/
if(empty($fname))
{
$fname = $currPart;
}
else
{
$lnameBuffer[] = $currPart;
}
}
// Join the last name buffer to populate the $lname variable
$lname = implode(' ', $lnameBuffer);
// The rest of the input buffer contains the address
$newAddress = implode(' ', $parts);
echo 'fname: '.$fname.PHP_EOL;
echo 'lname: '.$lname.PHP_EOL;
echo 'newAddress: '.$newAddress.PHP_EOL;
You could however achieve this much more easily using regex.
$testString = 'John doe smith villalobos garcia navarro 123 Main st 77555';
preg_match('/([^\s]\S+)\s([^\d]*)(.*)/', $testString, $matches);
$fname = $matches[1];
$lname = $matches[2];
$newAddress = $matches[3];
echo 'fname: '.$fname.PHP_EOL;
echo 'lname: '.$lname.PHP_EOL;
echo 'newAddress: '.$newAddress.PHP_EOL;
If your string is always formatted like "firstname lastname everything else is the address" you can just pass explode a limit like so:
$str = 'John doe 123 Main st 77555';
$parts = explode(' ', $str, 3);
var_dump($parts);
//array(3) {
// [0]=>
// string(4) "John"
// [1]=>
// string(3) "doe"
// [2]=>
// string(17) "123 Main st 77555"
//}
If you need to split with a rule like 'the first time we see a number indicates the start of an address' you can just find that and split the string up like so:
$str = 'john doe smith 123 fake street paris france';
$matches = [];
preg_match('/[0-9]/', $str, $matches, PREG_OFFSET_CAPTURE);
$numberPosition = $matches[0][1]; // this is the first matching element, and its position
$left = trim(substr($str, 0, $numberPosition)); // left side of the found number
$right = trim(substr($str, $numberPosition)); // right side of the found number
var_dump([
$left, $right
]);
//array(2) {
// [0]=>
// string(20) "john doe smith"
// [1]=>
// string(26) "123 fake street paris france"
//}

Replacing a string while choosing the order in which the part of strings get replaced first

I'm trying to replace a string with certain words, but I also want to replace it in order of the position in the array. For example, I want to replace "b c", before I try to replace "a b", without changing the position in the original string. By the way, the letters are suppose to represent actual words, and they are not supposed be part of another word. For example, the word "sun" is part of "sunflower", and the word "sunflower" cannot be replaced just because the word "sun" is in it.
$text = "a b c";
$replacement = array("a b" => "ab","b c" => "bc");
$search = array_map(function($v){
return preg_quote($v, "/");
}, array_keys($replacement));
echo $text = preg_replace_callback("/\b(" . implode("|", $search) . ")\b/", function($m)use($replacement){
return $replacement[$m[1]];
}, $text);
First Result
ab c
Second Result
I switched the position in the array around, thinking that it would affect the order of which the strings get replaced. Sadly, it doesn't work like that, and I got the same result.
$replacement = array("b c" => "bc","a b" => "ab");
ab c
At this point, I realize that it wasn't the position of the array that affects which part of the string that get replaced first, but the order of the part of strings that shows up on the original string that determines the order in which it is replaced by.
So, my question is, is there a way to somehow make it so that it can replace the string in order according to the order in which it is in the array, or in a different way? For example, I want to replace
"b c"
before I try to replace "a b" without changing the position of the original string. Is that doable? Thanks.
[EDIT]
The idea consists to cast the original text to an array (with one element at the beginning, the text). Array items at even index are splitted for each patterns. Since PREG_SPLIT_DELIM_CAPTURE option is used, delimiters have always an odd index and stay untouched once they are matched.
$text = 'a b c';
$rep = ['b c'=>'bc', 'a b'=>'ab', ];
$pats = array_map(function($i) {
return '~\b(' . preg_quote($i, '~') . ')\b~';
}, array_keys($rep));
$parts = (array)$text; // or $parts = [ $text ]; // it's the same
foreach ($pats as $pat) {
$temp = [];
foreach ($parts as $k=>$part) {
if ($k & 1)
$temp[] = $part;
else
$temp = array_merge(
$temp,
preg_split($pat, $part, -1, PREG_SPLIT_DELIM_CAPTURE)
);
}
$parts = $temp;
}
$result = '';
foreach ($parts as $k=>$part) {
$result .= ($k & 1) ? $rep[$part] : $part;
}
echo $result;
I changed your code to represent what (I think) you wanted:
$text = "a b c a b";
$replacement = array("b c" => "bc", "a b" => "ab");
$search = array_map(function($v){
return preg_quote($v, "/");
}, array_keys($replacement));
for($i = 0; $i < count($replacement); $i++) {
$regex = "/\b(" . $search[$i] . ")\b/";
echo $text = preg_replace_callback($regex, function($m)use($replacement){
return $replacement[$m[1]];
}, $text);
echo "<br>";
}
Basically, instead of relying on the regex to do that work I do a for loop to go through each replacement and create the regex. That way the order of the array matters. I also changed the initial $text to test if it worked

How to grab number after a word or symbol in PHP?

I want to grab a text with PHP just like for an example, There is a data "The apple=10" and I want to grab only the numbers from the data which looks exactly like that. I mean, the number's place would be after 'equals'.
and my problem is that the number from the source can be 2 or 3 characters or on the other word it is inconstant.
please help me to solve them :)
$string = "Apple=10 | Orange=3 | Banana=7";
$elements = explode("|", $string);
$values = array();
foreach($elements as $element)
{
$element = trim($element);
$val_array = explode("=", $element);
$values[$val_array[0]] = $val_array[1];
}
var_dump($values);
Output:
array(3) {
["Apple"]=> string(2) "10"
["Orange"]=> string(1) "3"
["Banana"]=> string(1) "7"
}
Hope thats how you need it :)
Well, php is a bit lazy about int conversion, so 12345blablabla can be converted to 12345:
$value = intval(substr($str, strpos($str, '=') + 1));
Of course, this is not the cleanest way but it is simple. If you want something cleaner, you could use a regexp:
preg_match ('#=([0-9]+)#', $str, $matches);
$value = intval($matches[1]) ;
Try the below code:
$givenString= "The apple=10";
$required_string = substr($givenString, strpos($givenString, "=") + 1);
echo "output = ".$required_string ; // output = 10
Using strpos() function, you can Find the position of the first occurrence of a substring in a string
and substr() function, Return part of a string.

How to get the value of an array after first index?

I have an array which contains the full name. I know how to display the last name which basically resides in the 1st index. How can I display the rest of the values after the last name?
$fullname = array('fullname' => 'POTTER Harry James');
$res = implode("", $fullname);
$name = preg_split("/[\s,]+/", $res);
$lname = $name[0];
What i did in the first name:
$fname = $name[1]. " ".$name[2];
It works fine, but is there a cleaner way to do that? I mean, what if the user has more than 2 first names?
Thanks.
I suggest to use explode() function:
<?php
$fullname = array('fullname' => 'POTTER Harry James');
$parts = explode(' ', $fullname['fullname']);
var_dump($parts);
?>
Shows:
array(3) {
[0]=>
string(6) "POTTER"
[1]=>
string(5) "Harry"
[2]=>
string(5) "James"
}
You might use any part of $parts in a way, that you need.
<?php
$a = array_shift($parts);
$b = implode(' ', $parts);
echo "{$b} ({$a})"; // Harry James (POTTER)
?>
UPDv1:
In your current code, you might do just the same thing:
<?php
$lname = array_shift($name);
$fname = implode(' ', $name);
?>
I think you should take out the last name off the array first, then use a loop to concatenate the remaining names as fistname.
$fullname = array('fullname' => 'POTTER Harry James');
$res = implode("", $fullname);
$name = preg_split("/[\s,]+/", $res);
$lname = array_shift($name);
$fname = "";
foreach($name as $fnames)
$fname.= " ".$fnames;
$fullname = array('fullname' => 'POTTER Harry James');
$firstNames = strstr($fullname['fullname'], ' '); // $firstNames='Harry James'
This gets the string after the first space character.
This is a bit of an impossible task. If left to their own devices, users are going to put all sorts of stuff into a single field.
If you care about separating the first and last names of your users, you should ask for them separately, as there is no regex that can possibly determine the correct way to break up their name.
You could do
<?php
$fullname = array('fullname' => 'POTTER Harry James');
list($lname,$fname) = explode(" ", $fullname["fullname"],2);
echo $fname."<br>".$lname;
?>
This will work if the name contains 2 words or more. In case there are more than 2 words then anything except the first word will be considered as first name and first word will be considered as the last name.

Inserting a space 2 places after a decimal in a string

In PHP, I am importing some text files containing tables of float values that are space delimited. All values contain two decimal places. A typical line would look like this:
1.45 22.87 99.12 19.55
However, some lines, if the number before the decimal is 3 digits long, the original file sometimes does not include a space. So what should be:
1.45 122.87 99.12 19.55
comes in as:
1.45122.87 99.12 19.55
What I assume I need to do is search the string for decimals, then look 2 spaces after that, and if there is not a space there I need to add one. I just cannot for the life of me figure out the most direct way to do so.
I would use regex:
$pattern = "/(-)?\d{1,}\.\d{2}/";
preg_match_all($pattern, "1.45122.87 99.12 19.55", $matches);
print_r($matches);
DEMO
This does what you want. Probably not the most efficient way to do it though.
<?php
$line = "1.45122.87 99.12 19.55";
$length = strlen($line);
$result = '';
$i=0;
while ($i<$length)
{
if ($line[$i] == '.')
{
$result .= $line[$i];
$result .= $line[$i+1];
$result .= $line[$i+2];
$result .= ' ';
$i += 3;
}
else if ($line[$i] == ' ')
{
$i++;
}
else
{
$result .= $line[$i];
$i++;
}
}
echo $result;
?>
This is a fixed-column-width file. I would parse these by substr().
http://php.net/manual/en/function.substr.php
for ($x=0; $x<strlen($line); $x+=4) {
$parts[] = trim(substr($line, $x, 4));
}
This will get you an array in $parts of all the fields. This is untested, but should work.
$line = '1.45122.87 99.12 19.55';
preg_match_all('~([0-9]{1,3}\.[0-9]{2})~', $line, $matches);
var_dump($matches[1]);
/*
Result:
array(4) {
[0]=>
string(4) "1.45"
[1]=>
string(6) "122.87"
[2]=>
string(5) "99.12"
[3]=>
string(5) "19.55"
}
*/
you could use preg_split() to create an array of the line using regex
$lineArray = preg_split("/(\d+(\.\d{1,2})?)/", $lineOfNumbers);
This would find all instances of ####.## and not worry about the spaces
I would do something like this, say the line of decimals is in a variable called $line:
$parts = explode(' ', $line);
Now you have an array of decimals values, so
$parts[0] = "1.45"
(float)$parts[0] = 1.45
$parts[1] = "122.87"
(float)$parts[1] = 122.87
// etc...

Categories