I have the following string in PHP:
System load: 0.0 Processes: 119 Usage of /: 0.8% of 226.04GB Users logged in: 1 Memory usage: 4% IP address for eth0: 192.168.0.21 Swap usage: 0% Graph this data and manage this system at https://landscape.canonical.com/
I'm trying to split it up into strings for each value so I can get "0.0", "119", "0.8% of 226.04GB", "1", "4%", "192.168.0.21", "0%".
I did try using set locations in the string to pick out the data but realised it was no good as the values are dynamic and could change from being 1 to 4+ characters long at any time. Is there a way I can split these up using PHP? I was unable to find anything in the string function library. Thanks.
http://www.phpliveregex.com/p/2kT
$input = 'System load: 0.0 Processes: 119 Usage of /: 0.8% of 226.04GB Users logged in: 1 Memory usage: 4% IP address for eth0: 192.168.0.21 Swap usage: 0% Graph this data and manage this system at https://landscape.canonical.com/';
$results = array();
preg_match_all("/\d[^\s:]*/", $input, $results);
$results will look like this:
Array
(
[0] => Array
(
[0] => 0.0
[1] => 119
[2] => 0.8%
[3] => 226.04GB
[4] => 1
[5] => 4%
[6] => 0
[7] => 192.168.0.21
[8] => 0%
)
)
A sample regular expression that just grabs groups (untested):
System load: (\d+.\d) Processes: (\d+) Usage of /: (\d+.\d)% of (\w+) Users logged in: (\d+) Memory usage: (\d+%) IP address for eth0: (\d{1,3}.\d{1,3}.\d{1,3}.\d{1,3}) Swap usage: (\d+%) Graph this data and manage this system at https://landscape.canonical.com/
It's quite vulnerable to slight changes though, like extra spaces etc. It'd be much easier to just grab this information from different places, like df. Some even are available as standard PHP functions, like sys_getloadavg().
$str = 'System load: 0.0 Processes: 119 Usage of /: 0.8% of 226.04GB Users logged in: 1 Memory usage: 4% IP address for eth0: 192.168.0.21 Swap usage: 0% Graph this data and manage this system at https://landscape.canonical.com/';
$regex = '/^(?:System\s+load\:\s+)(\d+\.\d+)(?:\s+Processes\:\s+)(\d+)(?:\s+Usage\s+of\s+\/\:\s+)(\d+\.\d+\%\sof\s\d+\.\d+GB)(?:\s+Users\s+logged\s+in\:\s+)(\d+)(?:\s+Memory\s+usage\:\s+)(\d+\%)(?:\s+IP\s+address\s+for\s+eth\d+\:\s+)(\d+\.\d+\.\d+\.\d+)(?:\s+Swap\s+usage\:\s+)(\d+\%)(?:\s+Graph\s+this\s+data.+)$/';
preg_match_all($regex, $str, $x);
echo '<pre>'.print_r($x, 1);
don't worry about spaces ;)
Related
I have a string which returns data usage in B, KB, MB and so on. I want to separate the number and string part of it.
Ex : 14.5 MB - I want 14.5 and MB separately.
I tried using regex
'/(\d+)(\w)/'
but does not give the desired result.
Expected result
Array( [0] => 14.5, [1] => 'MB' )
You can make use of explode function if you are sure that your string will always contains space in between
$consumedData = '14.5 MB';
$withSeperate = explode(' ',$consumedData);
var_dump($withSeperate);
Output
Array([0] => 14.5, [1] => 'MB');
You may try using preg_match_all here with the following regex pattern:
\b(\d+(?:\.\d+)?)\s*([KMGT]?B)\b
This matches a (possibly) decimal size, followed by a unit based in bytes.
$input = "Here are three sizes 14.5 MB, 10B, and 30.8 GB";
preg_match_all("/\b(\d+(?:\.\d+)?)\s*([KMGT]?B)\b/", $input, $matches);
print_r($matches[1]);
print_r($matches[2]);
This prints:
Array
(
[0] => 14.5
[1] => 10
[2] => 30.8
)
Array
(
[0] => MB
[1] => B
[2] => GB
)
I'm working in PHP and need to parse strings looking like this:
Rake (100) Pot (1000) Players (andy: 10, bob: 20, cindy: 70)
I need to get the rake, pot, and rake contribution per player with names. The number of players is variable. Order is irrelevant so long as I can match player name to rake contribution in a consistent way.
For example I'm looking to get something like this:
Array
(
[0] => Rake (100) Pot (1000) Players (andy: 10, bob: 20, cindy: 70)
[1] => 100
[2] => 1000
[3] => andy
[4] => 10
[5] => bob
[6] => 20
[7] => cindy
[8] => 70
)
I was able to come up with a regex which matches the string but it only returns the last player-rake contribution pair
^Rake \(([0-9]+)\) Pot \(([0-9]+)\) Players \((?:([a-z]*): ([0-9]*)(?:, )?)*\)$
Outputs:
Array
(
[0] => Rake (100) Pot (1000) Players (andy: 10, bob: 20, cindy: 70)
[1] => 100
[2] => 1000
[3] => cindy
[4] => 70
)
I've tried using preg_match_all and g modifiers but to no success. I know preg_match_all would be able to get me what I wanted if I ONLY wanted the player-rake contribution pairs but there is data before that I also require.
Obviously I can use explode and parse the data myself but before going down that route I need to know if/how this can be done with pure regex.
You could use the below regex,
(?:^Rake \(([0-9]+)\) Pot \(([0-9]+)\) Players \(|)(\w+):?\s*(\d+)(?=[^()]*\))
DEMO
| at the last of the first non-capturing group helps the regex engine to match the characters from the remaining string using the pattern which follows the non-capturing group.
I would use the following Regex to validate the input string:
^Rake \((?<Rake>\d+)\) Pot \((?<Pot>\d+)\) Players \(((?:\w*: \d*(?:, )?)+)\)$
And then just use the explode() function on the last capture group to split the players out:
preg_match($regex, $string, $matches);
$players = explode(', ', $matches[2]);
Right now I'm using the command below to get the volume names of the mounted disks in OSX:
$exec = "df -lH | grep \"/Volumes/*\" | tr -s \" \" | sed 's/ /;/g'";
And parsing the output using this code:
$lines = explode("\n", $output);
$i = 0;
foreach ($lines as $line) {
$driveinfo = explode(";", $line);
$driveinfo[7] = trim($driveinfo[0]);
if (!empty($driveinfo[0]))
$allremovabledrives[$driveinfo[0]] = $driveinfo;
$i++;
}
This works fine if the Volume label doesn't have spaces in it:
[/dev/disk1s1] => Array
(
[0] => /dev/disk1s1
[1] => 32G
[2] => 31G
[3] => 674M
[4] => 98%
[5] => 0
[6] => 0
[7] => /dev/disk1s1
[8] => /Volumes/LUMIX
)
But if I mount a disk with a volume name that has spaces, disaster strikes and extra array values get added:
[/dev/disk4] => Array
(
[0] => /dev/disk4
[1] => 4.0T
[2] => 1.2T
[3] => 2.8T
[4] => 29%
[5] => 140741078
[6] => 347553584
[7] => /dev/disk4
[8] => /Volumes/My
[9] => Passport
[10] => Pro
)
Can anybody help me solve this problem? I'm not well versed in sed and command-line utilities ...
OK, the volume name is always the last field, and you know how many fields there are (9), so I would just split on whitespace and ask for that many fields. And not bother with any sed/awk/grep/tr stuff since you're already in a full-fledged programming system that can do what those commands do more efficiently within its own process space.
First, you can pass the list of volumes you want info about to df as arguments, which means you don't need the grep:
$df = shell_exec('df -lH /Volumes/*');
Now split on newline and get rid of the headers:
$rows = explode("\n", $df);
array_shift($rows);
Start building your result:
$result = array();
Here's where we don't need to use shell utilities just to make it possible to do with explode what we can already do with preg_split. The regular expression /\s+/ matches 1 or more whitespace characters in a row, so we don't get extra fields. The limit (9) means it only splits into 9 fields no matter how many more spaces there are - so the spaces in the last field (the volume name) get left alone.
foreach ($rows as $row) {
$cols = preg_split('/\s+/', $row, 9);
$result[$cols[0]] = $cols;
}
After all that, $result should look like you want.
Having some issues integrating PHP and R. I am working from this article:
http://www.r-bloggers.com/integrating-php-and-r/
R is installed and is verified working with our R script:
Rscript C:\inetpub\wwwroot\client\includes\decisionTreePredictor.R 20 10 O 1000 10000 5000 0.2 10.2
Printing a single value that is a result of its calculations:
[1] "0"
(The path to Rscript.exe is set in the Windows environmental variables)
I have a PHP script in place that is using exec() which tests successfully with commands such as:
$result = exec('dir',$output,$returnVar);
echo "<br>result ". print_r($result,true);
echo "<br>output <pre>". print_r($output,true) , "</pre>";
echo "<br>return ". print_r($returnVar,true);
returning:
result 2 Dir(s) 117,749,354,496 bytes free
output
Array
(
[0] => Volume in drive C is C_DRIVE
[1] => Volume Serial Number is 7EB2-A074
[2] =>
[3] => Directory of C:\inetpub\wwwroot\client\temp
[4] =>
[5] => 05/17/2014 10:29 PM .
[6] => 05/17/2014 10:29 PM ..
[7] => 05/16/2014 09:24 AM 5,181 dbimporttest.php
[8] => 05/17/2014 10:29 PM 0 routput.txt
[9] => 05/17/2014 11:42 PM 701 rscripttest.php
[10] => 05/16/2014 04:59 PM 425 whoami.php
[11] => 4 File(s) 6,307 bytes
[12] => 2 Dir(s) 117,749,354,496 bytes free
)
return 0
When I try to run the R script within the exec command, it fails:
$result = exec('Rscript.exe C:\inetpub\wwwroot\client\includes\decisionTreePredictor.R 20 10 O 1000 10000 5000 0.2 10.2',$output,$returnVar);
echo "<br>result ". print_r($result,true);
echo "<br>output <pre>". print_r($output,true) , "</pre>";
echo "<br>return ". print_r($returnVar,true);
Returning:
result
output
Array
(
)
return 1
I am running:
Windows Server 8 R2
IIS 8
PHP 5.5
R 3.1
Unable to get exec() to work or output errors that are usable, I decided to seek an alternative route. Using the COM class seems to have given me what I was looking for.
Here is the final, operational code:
$command = 'C:\Program Files\R\R-3.1.0\bin\Rscript.exe C:\inetpub\wwwroot\client\includes\decisionTreePredictor.R 20 10 O 1000 10000 5000 0.2 10.2';
$pCom = new COM("WScript.Shell");
$pShell = $pCom->Exec($command);
$sStdOut = $pShell->StdOut->ReadAll; # Standard output
$sStdErr = $pShell->StdErr->ReadAll; # Error
echo "<pre>$sStdOut</pre>";
Odd that I couldn't get exec() to do the job as that seems be the solution preferred by most bloggers discussing R/PHP integration.
Anyway, I hope this solution helps anyone else that finds themselves in my situation!
P.S. You will want to make sure the extension is on in php.ini (it is off by default on install): extension=php_com_dotnet.dll
I'm using str_getcsv to parse tab separated values being returned from a nosql query however I'm running into a problem and the only solution I've found is illogical.
Here's some sample code to demonstrate (FYI, it seems the tabs aren't being preserved when showing here)...
$data = '0 16 Gruesome Public Executions In North Korea - 80 Killed http://www.youtube.com/watch?v=Dtx30AQpcjw&feature=youtube_gdata "North Korea staged gruesome public executions of 80 people this month, some for offenses as minor as watching South Korean entertainment videos or being fou... 1384357511 http://gdata.youtube.com/feeds/api/videos/Dtx30AQpcjw 0 The Young Turks 1 2013-11-13 12:53:31 9ab8f5607183ed258f4f98bb80f947b4 35afc4001e1a50fb463dac32de1d19e7';
$data = str_getcsv($data,"\t",NULL);
echo '<pre>'.print_r($data,TRUE).'</pre>';
Pay particular attention to the fact that one column (beginning with "North Korea...." actually starts with a double quote " but doesn't finish with one. This is why I supply NULL as the third parameter (enclosure) to override the defaut " enclosure value.
Here is the result:
Array
(
[0] => 0
[1] => 16
[2] => Gruesome Public Executions In North Korea - 80 Killed
[3] => http://www.youtube.com/watch?v=Dtx30AQpcjw&feature=youtube_gdata
[4] =>
[5] => North Korea staged gruesome public executions of 80 people this month, some for offenses as minor as watching South Korean entertainment videos or being fou... 1384357511 http://gdata.youtube.com/feeds/api/videos/Dtx30AQpcjw 0 The Young Turks 1 2013-11-13 12:53:31 9ab8f5607183ed258f4f98bb80f947b4 35afc4001e1a50fb463dac32de1d19e7
)
As you can see the quote is breaking the function. Logically I thought I would be able to use NULL or and empty string'' as the third parameter for str_getcsv (enclosure) but neither worked?!?!
The only thing I could use to get str_getcsv to work properly was a space char ' '. That doesn't make any sense to me becuase none of the columns have whitespace starting and/or ending them.
$data = '0 16 Gruesome Public Executions In North Korea - 80 Killed http://www.youtube.com/watch?v=Dtx30AQpcjw&feature=youtube_gdata "North Korea staged gruesome public executions of 80 people this month, some for offenses as minor as watching South Korean entertainment videos or being fou... 1384357511 http://gdata.youtube.com/feeds/api/videos/Dtx30AQpcjw 0 The Young Turks 1 2013-11-13 12:53:31 9ab8f5607183ed258f4f98bb80f947b4 35afc4001e1a50fb463dac32de1d19e7';
$data = str_getcsv($data,"\t",' ');
echo '<pre>'.print_r($data,TRUE).'</pre>';
Now the result is:
Array
(
[0] => 0
[1] => 16
[2] => Gruesome Public Executions In North Korea - 80 Killed
[3] => http://www.youtube.com/watch?v=Dtx30AQpcjw&feature=youtube_gdata
[4] =>
[5] => "North Korea staged gruesome public executions of 80 people this month, some for offenses as minor as watching South Korean entertainment videos or being fou...
[6] => 1384357511
[7] => http://gdata.youtube.com/feeds/api/videos/Dtx30AQpcjw
[8] => 0
[9] => The Young Turks
[10] =>
[11] =>
[12] =>
[13] =>
[14] => 1
[15] => 2013-11-13 12:53:31
[16] => 9ab8f5607183ed258f4f98bb80f947b4
[17] => 35afc4001e1a50fb463dac32de1d19e7
)
So my question is, why does it work with a space as the enclosure, but not NULL or and empty string? Also are there repercussions to this?
UPDATE 1: It seems this reduced the number of errors I was receiving in our logs but it didn't eliminate them, so I'm guessing that the I used as the enclosure has caused unintended side effects, albeit less troubling than the previous problem. But my question remains the same, why can't I use NULL, or an empty space as the enclosure, and secondly, is there a better way of dealing with / doing this?
Just to give a starting point ...
You might wanna consider working with the string itself, instead of using a function like str_getcsv in your case.
But be aware that there are at least some pitfalls, if you choose this route (might be your only option though):
Handling of escaped characters
Line breaks within the data (not meant as delimiters)
If you know that you don't have any other TABS in your string other than those ending the fields, and you don't have any linebreaks other than those delimiting a row, you might be fine with this:
$data = explode("\n", $the_whole_csv_string_block);
foreach ($data as $line)
{
$arr = explode("\t", $line);
// $arr[0] will have every first field of every row, $arr[1] the 2nd, ...
// Usually this is what I want when working with a csv file
// But if you rather want a multidimensional array, you can simply add
// $arr to a different array and after this loop you are good to go.
}
Otherwise this is just a starting point for you, to begin and tweak it to your individual situation, hope it helps.
Simply use chr(0) as enclosure and escape:
$data = str_getcsv($data, "\t", chr(0), chr(0));