Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
people
I have a problem I want to read from a file and use and fetch some parts of the file like below. This is whats inside the file but I want to fetch the names. This file is used by my server and if a player logs in the server then the list of names get bigger. But I have no clue how to do it.. and I really want to know how to do so.
I already tryed stuff myself by exploding the first characters but thats how far my knowledge reaches.
Already Big thanks for the one so kind to help me out.
Players online: NAME1, NAME2, NAME3, NAME4, NAME5, NAME6, ETC, ETC. Total: 4
You can try this out :
$line = 'layers online: NAME1, NAME2, NAME3, NAME4, NAME5, NAME6, ETC, ETC. Total: 4';
$pattern = '/:(.*)[,.]/';
preg_match($pattern, $line, $matches);
$names = explode(',', $matches[1]);
print_r($names);
You could search for the first occurance of the : character and the position of Total: using strpos() and then use substr() to remove these unneeded parts from the string. You could then split the string on each , character to get an array of names. Notice that the names will contain spaces so we could use array_walk() in conjunction with trim() to remove these:
// get the contents of your file
$data = file_get_contents('file.txt');
// get position of first ':' character
$pos1 = strpos($data, ':');
// get position of 'Total:'
$pos2 = strrpos($data, 'Total:');
// remove these parts using `substr()`
$data = substr($data, $pos1+1, ($pos2 - 1) - $pos1);
// split the string on each ',' character
$array = explode(",", $data);
// remove any whitespaces from the start and end
array_walk($array, function(&$value, $key) {
$value = trim($value);
});
// array now contains
Array
(
[0] => Admin Wouter
[1] => Krachtpatser
[2] => Dark Warrior
[3] => Anneleen.
)
To make sure you don't have any trailing '.' after a name you could modify the array_walk() callback like this:
array_walk($array, function(&$value, $key) {
// trim whitespaces
$value = trim($value);
// trim trailing '.' characters
$value = rtrim($value, '.');
});
$s = 'Players online: Admin Wouter, Krachtpatser, Dark Warrior, Anneleen. Total: 4';
// or read from the players file:
//$s = file_get_contents('path_to_players_file');
$s = str_replace('Players online: ', '', $s);
$stringPlayers = substr($s, 0, strrpos($s, '. Total:'));
echo $stringPlayers; // displays: Admin Wouter, Krachtpatser, Dark Warrior, Anneleen
// now get the player names in an array:
$arrayPlayers = explode(',', $stringPlayers);
foreach ($arrayPlayers as $k => $name) {
$arrayPlayers[$k] = trim($name);
}
echo '<pre>';
print_r($arrayPlayers);
echo '</pre>';
/* Displays:
Array
(
[0] => Admin Wouter
[1] => Krachtpatser
[2] => Dark Warrior
[3] => Anneleen
)
*/
Related
I've recently started working with PHP and am trying to make a list from a .txt BUT removing all the unnecessary components.
a line got this
item = 0 egg came_from_chicken
I want to remove the item = and the came_from_chicken which leaves me with 0 egg.
Now after some searching I've found substr() to remove the first 5 characters of each of my lines. Later I've also found that strtok() can remove the rest of the unwanted text after the second tab. Unfortunately I cannot combine these. So my question is: How to remove the first 5 chars from each line and remove everything after the second tab from each line?
I've got this so far:
<?php
$lines = file('../doc/itemlist.txt');
$newf = array();
foreach ($lines as $line) {
$newf[] = strtok($line, "\t") . "\t" . strtok("\t");
}
var_dump($newf);
?>
This works like a charm to remove everything after egg but still have to remove item =.
The quick-and-dirty way is to just wrap it all:
$newf[] = substr(strtok($line, "\t") . "\t" . strtok("\t"), 5);
But, I personally have a dislike for strtok() (can't explain why, I just don't like it). If you don't need to strip everything off from the second tab, but from the last tab (in your example the second tab is the last tab), I would use strrpos() to find the location of the last tab, and dump that into substr():
$newf[] = substr($line, 5, strrpos($line, "\t")-5);
That -5 is to compensate for the 5 characters you strip off from the beginning. If you need to start at character 6 instead of 5, you should also subtract 6 from whatever strrpos() returns.
Edit Never mind that whole last part, I just saw the example format you posted and you really need the second tab instead of the last tab.
You can use a regular expression:
<?php
$lines = file('./file.txt');
$newf = array();
foreach ($lines as $line) {
$newf[] = preg_replace('/.*=\s*(.*)\t.*/s', '$1', $line);
}
var_dump($newf);
Output:
array(1) {
[0]=>
string(5) "0 egg"
}
Assuming that you will be receiving similar patterns to the example you gave.
You can just do a simple line of:
$str = "item = 0 egg came_from_chicken";
$parts = preg_split('/\s+/', $str);
echo $parts[2] . $parts[3];
I know this is not the answer you are looking for using strtok but I believe it would be much easier to do the following code below:
<?php
$lines = '../doc/itemlist.txt';
// array to store all data
$newf = array();
foreach ($lines as $line) {
// you can do an explode which will turn it into an array and you can then get any values you want
// $newf [] = strtok ($line, "\t") . "\t" . strtok("\t"); // throw away
// lets say we use [item = 0 egg came_from_chicken] as our string
// we split it into an array for every tab or spaces found
$values = preg_split ('/\s+/', $line);
//returns
// Array
// (
// [0] => item
// [1] => =
// [2] => 0
// [3] => egg
// [4] => came_from_chicken
// [5] =>
// )
// lastly store your values which would be sub 2 and sub 4
$newf [] = $values [2] . ' ' . $values [3];
}
var_dump($newf);
// return
// array (size=3)
// 0 => string '0 aaa' (length=5)
// 1 => string '1 bbb' (length=5)
// 2 => string '2 ccc' (length=5)
?>
This approach will work with any string preceeding the = symbol.
foreach ($lines as $line) {
$newf[] = implode("\t", array_slice(explode("\t", trim(explode('=', $line, 2)[1])), 0, 2));
}
I am scraping the following kind of strings from an external resource which I can't change:
["one item",0,0,2,0,1,"800.12"],
["another item",1,3,2,5,1,"1,713.59"],
(etc...)
I use the following code to explode the elements into an array.
<?php
$id = 0;
foreach($lines AS $line) {
$id = 0;
// remove brackets and line end comma's
$found_data[] = str_replace(array('],', '[',']', '"'), array('','','',''), $line);
// add data to array
$results[$id] = explode(',', $line);
}
Which works fine for the first line, but as the second line uses a comma for the thousands seperator of the last item, it fails there. So somehow I need to disable the explode to replace stuff between " characters.
If all values would be surrounded by " characters, I could just use something like
explode('","', $line);
However, unfortunately that's not the case here: some values are surrounded by ", some aren't (not always the same values are). So I'm a bit lost in how I should proceed. Anyone who can point me in the right direction?
You can use json_decode here since your input string appears to be a valid json string.
$str = '["another item",1,3,2,5,1,"1,713.59"]'
$arr = json_decode($str);
You can then access individual indices from resulting array or print the whole array using:
print_r($arr);
Output:
Array
(
[0] => another item
[1] => 1
[2] => 3
[3] => 2
[4] => 5
[5] => 1
[6] => 1,713.59
)
I am trying to get the integer on the left and right for an input from the $str variable using REGEX. But I keep getting the commas back along with the integer. I only want integers not the commas. I have also tried replacing the wildcard . with \d but still no resolution.
$str = "1,2,3,4,5,6";
function pagination()
{
global $str;
// Using number 4 as an input from the string
preg_match('/(.{2})(4)(.{2})/', $str, $matches);
echo $matches[0]."\n".$matches[1]."\n".$matches[1]."\n".$matches[1]."\n";
}
pagination();
How about using a CSV parser?
$str = "1,2,3,4,5,6";
$line = str_getcsv($str);
$target = 4;
foreach($line as $key => $value) {
if($value == $target) {
echo $line[($key-1)] . '<--low high-->' . $line[($key+1)];
}
}
Output:
3<--low high-->5
or a regex could be
$str = "1,2,3,4,5,6";
preg_match('/(\d+),4,(\d+)/', $str, $matches);
echo $matches[1]."<--low high->".$matches[2];
Output:
3<--low high->5
The only flaw with these approaches is if the number is the start or end of range. Would that ever be the case?
I believe you're looking for Regex Non Capture Group
Here's what I did:
$regStr = "1,2,3,4,5,6";
$regex = "/(\d)(?:,)(4)(?:,)(\d)/";
preg_match($regex, $regStr, $results);
print_r($results);
Gives me the results:
Array ( [0] => 3,4,5 [1] => 3 [2] => 4 [3] => 5 )
Hope this helps!
Given your function name I am going to assume you need this for pagination.
The following solution might be easier:
$str = "1,2,3,4,5,6,7,8,9,10";
$str_parts = explode(',', $str);
// reset and end return the first and last element of an array respectively
$start = reset($str_parts);
$end = end($str_parts);
This prevents your regex from having to deal with your numbers getting into the double digits.
I want to split a string such as the following (by a divider like '~##' (and only that)):
to=enquiry#test.com~##subject=test~##text=this is body/text~##date=date
into an array containing e.g.:
to => enquiry#test.com
subject => test
text => this is body/text
date => date
I'm using php5 and I've got the following regex, which almost works, but there are a couple of errors and there must be a way to do it in one go:
//Split the string in the url of $text at every ~##
$regexp = "/(?:|(?<=~##))(.*?=.*?)(?:~##|$|\/(?!.*~##))/";
preg_match_all($regexp, $text, $a);
//$a[1] is an array containing var1=content1 var2=content2 etc;
//Now create an array in the form [var1] = content, [var2] = content2
foreach($a[1] as $key => $value) {
//Get the two groups either side of the equals sign
$regexp = "/([^\/~##,= ]+)=([^~##,= ]+)/";
preg_match_all($regexp, $value, $r);
//Assign to array key = value
$val[$r[1][0]] = $r[2][0]; //e.g. $val['subject'] = 'hi'
}
print_r($val);
My queries are that:
It doesn't seem to capture more than 3 different sets of parameters
It is breaking on the # symbol and so not capturing email addresses e.g. returning:
to => enquiry
subject => test
text => this is body/text
I am doing multiple different regex searches where I suspect I would be able to do one.
Any help would be really appreciated.
Thanks
Why are you using regex when there is much simple method to do this by explode like this
$str = 'to=enquiry#test.com~##subject=test~##text=this is body/text~##date=date';
$array = explode('~##',$str);
$finalArr = array();
foreach($array as $val)
{
$tmp = explode('=',$val);
$finalArr[$tmp['0']] = $tmp['1'];
}
echo '<pre>';
print_r($finalArr);
Merchant Id|Merchant|Website|Transaction In Period|Voids In Period|Gross Sales Amount|Total Commision in Period
9766|Mountains Plus Outdoor Gear|www.MPGear.com|1|0|88.91|8.89
12447|Meritline.com|www.meritline.com|5|0|52.86|3.71
16213|East Coast Fashions|www.discountstripper.com|1|0|32.27|3.23
17226|HRM USA|www.HeartRateMonitorsUSA.com|1|0|189.9|6.65
I am getting above string from url now now I want convert that string to array based on split delimiter |
But there is a problem after end of each new row there is not placed delimiter | so I want that to placed that delimiter after each row end.
Note :: all columns will be predefined and it will return same all time request.
I am using this code to convert that string to array . This code is working perfect if there will be all delimiter placed correctly in string.
$NumColumns = 6;
$Delim = "|";
$data = array_chunk(explode($Delim,$contents), $NumColumns);
output will be like this
Array
(
[0] => Array
(
[0] => Merchant Id
[1] => Merchant
[2] => Website
[3] => Transaction In Period
[4] => Voids In Period
[5] => Gross Sales Amount
[6] => Total Commision in Period
)
[1] => Array
(
[0] => 9766
[1] => Mountains Plus Outdoor Gear
[2] => www.MPGear.com
[3] => 1
[4] => 0
[5] => 88.91
[6] => 8.89
)
-----
----
)
Try using str_getcsv or explode.
<?php
$data_from_url = "Merchant Id|Merchant|Website|Transaction In Period|Voids In Period|Gross Sales Amount|Total Commision in Period
9766|Mountains Plus Outdoor Gear|www.MPGear.com|1|0|88.91|8.89
12447|Meritline.com|www.meritline.com|5|0|52.86|3.71
16213|East Coast Fashions|www.discountstripper.com|1|0|32.27|3.23
17226|HRM USA|www.HeartRateMonitorsUSA.com|1|0|189.9|6.65";
$splitted_data = explode(PHP_EOL, $data_from_url);
/**
* print_r($splitted_data) will be
* Array
* (
[0] => "Merchant Id|Merchant|Website|Transaction In Period|Voids In Period|Gross Sales Amount|Total Commision in Period"
[1] => "9766|Mountains Plus Outdoor Gear|www.MPGear.com|1|0|88.91|8.89"
...
* )
*/
// You can now iterate through the lines
$output1 = array();
foreach($splitted_data as $row) {
$output1[] = str_getcsv(trim($row), '|'); // parses a
// OR
//$output1[] = explode('|', trim($row));
}
// OR use array_map with callback function
$output2 = array_map(function($line){ return explode('|', trim($line)); }, $splitted_data);
$output3 = array_map(function($line){ return str_getcsv(trim($line), '|'); }, $splitted_data);
var_dump($output1, $output2, $output3); // The result you want to achive
?>
I would do this as a 2-step process. First split it into lines on the \n (newline) character, and then split each line on the | character.
You can do that in only a couple lines, like this:
$lines = explode("\n", $contents);
$data = array_map(function($line) {return explode('|', trim($line));}, $lines);
You can see this working here: http://phpfiddle.org/main/code/9fv-h2c
Once I split the contents into individual lines, I'm using the array_map() function to apply the same operation to every element of the array (every line).
array_map() calls a callback function (which I define as an anonymous function) for each element in the array. In this instance, I've defined a simple function that trims the line to remove any extra spaces there may be, and then splits it on the | character to get the individual fields.
If the array_map line is a bit complicated, I could illustrate how it's working by rewriting it without the anonymous function like this:
function processLine($line) {
$line = trim($line);
$fields = explode('|', $line);
return $fields;
}
$data = array_map('processLine', $lines);
...or even rewriting it without using array_map like this:
function processLine($line) {
$line = trim($line);
$fields = explode('|', $line);
return $fields;
}
$data = array();
foreach ($lines as $l) {
$data[] = processLine($l);
}
If I understand your question correctly, you're trying to split the data, but want to keep the delimiter | as part of the string.
Using preg_split, you can do this like so:
$arr = preg_split('/([^|]*\|)/', $string, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
The expression matches zero or more chars that aren't | ([^|]*)
and matches the delimiting |. the combination of the two is used as delimiter. In other words, everything is a delimiter now.
That's why we have to use the predefined constant PREG_SPLIT_DELIM_CAPUTRE.
Of course, between the delimiters, there's nothing, but preg_split will capture this nothing-ness, too and add empty matches in the resulting array. That's why we have to use the other predefined constant: PREG_SPLIT_NO_EMPTY.
The two constants are combined by means of the bitwise OR operator |
$output = explode(PHP_EOL, $input);
foreach($output as &$line)
{//$line is a reference here, important!
$line = preg_split('/([^|]*\|)/', $line, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE);
}
This should produce the desired ouptut, assuming you want the delimiting | kept in the strings. if not:
$output = explode(PHP_EOL, $input);
foreach($output as &$line)
{
$line = explode('|', $line);
}
That's it, really...