Read fails with spaces - php

I am very new to PHP and want to learn. I am trying to make a top-list for my server but I have a problem. My file is built like this:
"Name" "Kills"
"^0user1^7" "2"
"user2" "2"
"user3" "6"
"user with spaces" "91"
But if I want to read this with PHP it fails because the user has spaces.
That's the method I use to read the file:
$lines = file('top.txt');
foreach ($lines as $line) {
$parts = explode(' ', $line);
echo isset($parts[0]) ? $parts[0] : 'N/A' ;
}
Maybe someone knows a better method, because this don't work very well :D.

You need REGEX :-)
<?php
$lines = array(
'"^0user1^7" "2"',
'"user2" "2"',
'"user3" "6"',
'"user with spaces" "91"',
);
$regex = '#"(?<user>[a-zA-Z0-9\^\s]+)"\s"(?<num>\d+)"#';
foreach ($lines as $line) {
preg_match($regex, $line, $matches);
echo 'user = '.$matches['user'].', num = '.$matches['num']."\n";
}
In the regex, we have # delimiters, then look for stuff between quotes. Using (?PATTERN) gives you a named capture group. The first looks for letters etc, the second digits only.
See here to understand how the regex is matching!
https://regex101.com/r/023LlL/1/
See it here in action https://3v4l.org/qDVuf

For your process this might help
$lines = file('top.txt');
$line = explode(PHP_EOL, $lines); // this will split file content line by line
foreach ($line as $key=>$value_line ) {
echo str_replace(" ","",$value_line);
}

As I commented above, below is a simple example with JSON.
Assuming, you have stored records in JSON format:
$json = '{
"user1": "12",
"sad sad":"23"
}';
$decoded = json_decode($json);
foreach($decoded as $key => $value){
echo 'Key: ' . $key . ' And value is ' . $value;
}
And here is the demo link: https://3v4l.org/ih1P7

Related

Reading information from CSS in PHP

I am creating a website where users shall be able to upload plugins with a file called 'info.css'. I want my PHP-file to be able to read out information from this file, for example the ID.
The 'info.css' file will contain something similar to:
/*
ID: test-preset;
Name: Test Preset;
*/
I want the ID and Name to get into separate strings, without the 'id:' or 'name:'.
Please write any solution you may will work. I have tried with following (but have gotten stuck on the way. Please note that the information in the 'info.css' file may appear in a different order, so for example it should work if the 'Name:' comes first.
$preset_inf = strtolower($preset_inf);
$preset_inf = explode('*/', $preset_inf);
$preset_inf = str_replace('/*', '', $preset_inf[0]);
$preset_inf = str_replace(' ', '', $preset_inf);
$preset_inf = explode(';', $preset_inf);
Regex?
$str = "/*
ID: test-preset;
Name: Test Preset;
*/";
preg_match_all("/(ID|Name):\s*(.*?)\;/s", $str, $m);
var_dump($m);
This will produce:
array(3) {
[0]=>
string(35) "ID: test-preset;
Name: Test Preset;"
[1]=>
string(11) "test-preset"
[2]=>
string(11) "Test Preset"
}
Matches anything between ID/Name and ;.
Edit noticed it could be the other way around too. Edited the code.
The output array will look slightly different but the part you want is in $m[2] array.
https://3v4l.org/iusmV
You can use regex to retrieve each variable, so:
preg_match( '/Name: (.*?);/', $css_file, $match );
$name = $match[1];
echo $name;
preg_match( '/ID: (.*?);/', $css_file, $match );
$id = $match[1];
echo $id;
Would return
Test Preset
test-preset
In case you need a more general solution, here is a regex that will parse a header with an arbitrary number of options along with their names:
$string = '/*
ID: test-preset;
Name: Test Preset;
*/';
$pattern = '/^(?!\/\*)([^:]+):([^:]+);$/mU';
preg_match_all($pattern, $string, $matches, PREG_SET_ORDER, 0);
$results = array();
foreach($matches as $match){
$results[$match[1]] = $match[2];
}
$results now contains an array with this structure:
[
"ID" => "test-preset",
"Name" => "Test Preset"
]
This has the benefit of being able to handle any number of "Header arguments".
Scalable solution.
$presetInfoItem = [];
$presetInfo = [];
$presetFile = "/*
ID: test-preset;
Name: Test Preset;
*/";
$fields = ['ID', 'Name'];
foreach ($fields as $field) {
$matchesCount = preg_match_all("#$field:(?'$field'[\w-\s]*);#", $presetFile, $presetInfoItem);
if ($matchesCount === 0 || $matchesCount === false) {
$presetInfo[$field] = "";
} else {
$presetInfo[$field] = trim($presetInfoItem[$field][0]);
}
}
var_export($presetInfo);
For your pleasure:
<?php
$css = '/*
ID: test-preset;
Name: Test Preset;
*/';
$css = str_replace("*/", "", $css);
$css = str_replace("/*", "", $css);
$css = str_replace(";", "", $css);
$css = trim($css);
$lines = explode("\n", str_replace("\r", '', $css));
if(!empty($lines)) {
foreach($lines as $i => $line) {
$vals = explode(":", $line);
$key = $vals[0];
$value = $vals[1];
echo '<div><b>'.$key.'</b>: '.$value.'</div>';
}
}
?>
Result is:
ID: test-preset
Name: Test Preset
Regex is not needed :)

Backreference preg_replace with commas in subject

Can you please help me find the preg_replace syntax so i can duplicate the price where it is missing?
The subject is:
...nomaterwhat13124123,"321,00",,nomaterwhat
...nomaterwhat12321,"322,20","134,00",nomaterwhat
...nomaterwhat1321,"211,00",,nomaterwhat
...nomaterwhat31313,"241,00",,nomaterwhat
My output want to be:
...nomaterwhat13124123,"321,00","321,00",nomaterwhat
...nomaterwhat12321,"322,20","134,00",nomaterwhat
...nomaterwhat1321,"211,00","211,00",nomaterwhat
...nomaterwhat31313,"241,00","241,00",nomaterwhat
I tried
preg_replace("(\W+),,nomaterwhat$", "$1,$1,nomaterwhat", $string);
Ignoring more complex cases this should do:
$result = preg_replace('/,"(\d+,\d{2})",,nomaterwhat/', ',"$1",$1,nomaterwhat', $string);
If you use str_getcsv you can do something like this:
$data = "CSV VALUES";
$lines = explode("\n", $data);
foreach ($lines as $line) {
$temp = str_getcsv($line);
echo '<pre>' . print_r($temp, true) . '</pre>';
}
Then you can put these into an array like so:
$data = "CSV VALUES";
$lines = explode("\n", $data);
$output = array();
foreach ($lines as $line) {
$temp = str_getcsv($line);
$temp[5] = ($temp[5] == '') ? $temp[4] : $temp[5];
$output[] = $temp;
}
echo '<pre>' . print_r($output, true) . '</pre>';
Replace $temp[5] with the place that the 2nd price should be.
You have a few issues with your regex.
1. No delimiter
2. No m modifier so $ is the end of the string, not line.
3. \W+ is a non a-z, 0-9, and/or _ so you wouldn't have gotten the
money value there anyway.
Try this out:
$string = '...nomaterwhat13124123,"321,00",,nomaterwhat
...nomaterwhat12321,"322,20","134,00",nomaterwhat
...nomaterwhat1321,"211,00",,nomaterwhat
...nomaterwhat31313,"241,00",,nomaterwhat';
echo preg_replace("/,(\"\d+,\d{2}\"),,nomaterwhat$/m", ",$1,$1,nomaterwhat", $string);
Output:
...nomaterwhat13124123,"321,00","321,00",nomaterwhat
...nomaterwhat12321,"322,20","134,00",nomaterwhat
...nomaterwhat1321,"211,00","211,00",nomaterwhat
...nomaterwhat31313,"241,00","241,00",nomaterwhat
Regex Demo: https://regex101.com/r/hE2zQ7/1
PHP Demo: http://ideone.com/OanPN1

How to use php to explode string, remove extra characters

I've been using PHP for a while and came across an issue where turning a string into an array (explode), and then simply removing system output characters around each element was not easy to achieve.
I have a string of categories where the output needs to be handled:
2;#Ecosystems;#3;#Core Science Systems (CSS);#4;#Energy and Minerals;#5;#Director
I have tried this particular code below:
$text = "2;#Ecosystems;#3;#Core Science Systems (CSS);#4;#Energy and Minerals;#5;#Director";
$explode = explode('#' , $text);
foreach ($explode as $key => $value)
{
ob_start();
echo ''.$value.'';
$myStr = ob_get_contents();
ob_end_clean();
}
echo "$myStr"
The only element returned is:
Director
Can someone point me in the right direction. I'd like to view the string like this:
Ecosystems; Core Science Systems (CSS); Energy and Minerals; Director
$myStr = ob_get_contents();
This will replace $myStr. What you're probably looking to do is add to it:
$myStr .= ob_get_contents();
Though looking at your required output, your code is not going to achieve what you want, because you're not removing the preceding part e.g. #1;.
Try this
$text = "2;#Ecosystems;#3;#Core Science Systems (CSS);#4;#Energy and Minerals;#5;#Director";
$text = preg_replace('/(#?[0-9];#)/', ' ', $text);
echo $text;
Output: Ecosystems; Core Science Systems (CSS); Energy and Minerals; Director
Your problem is not question-related, you overwrite your buffer with each foreach iteration, the fix is
$myStr .= ob_get_contents();
For this exact example you give you could change the explode to split on ;#
$text = "2;#Ecosystems;#3;#Core Science Systems (CSS);#4;#Energy and Minerals;#5;#Director";
$categories = array();
$explode = explode(';#' , $text);
foreach ($explode as $key => $value)
{
if (!is_numeric($value)) {
$categories[] = $value;
}
}
echo implode("; ", $categories);
The reason is that you place both ob_start() and ob_end_clean() inside the loop. Place them outside the loop:
ob_start();
foreach ($explode as $key => $value)
{
echo ''.$value.'';
$myStr = ob_get_contents();
}
ob_end_clean();
echo "$myStr";
I would use preg_split and do it like this:
$result = implode(' ', preg_split('/#?\d+;#/', $text, null, PREG_SPLIT_NO_EMPTY));
this solves the problem, you can fine-tune the output:
$text = "2;#Ecosystems;#3;#Core Science Systems (CSS);#4;#Energy and Minerals;#5;#Director";
$explode = explode('#' , $text);
$myStr = '';
foreach ($explode as $key => $value)
{
$myStr .= $value;
}
echo "$myStr"
$arr = explode("#", $text);
You can then echo the array in different ways
echo $arr[0] <= the number represents the index of the array value.

How can I remove certain lines in a multiline string?

My code is receiving a string which I have no control of, which I'll call $my_string. The string is the contents of a transcript. If I echo the string, like so:
echo $my_string;
I can see the contents, which look something like this.
1
00:00:00.000 --> 00:00:04.980
[MUSIC]
2
00:00:04.980 --> 00:00:08.120
Hi, my name is holl and I am here
to write some PHP.
3
00:00:08.120 --> 00:00:10.277
You can see my screen, here.
What I'd like to do is run this through a function so it's just the actual words spoken, removing all the lines that signify time, or the order.
[MUSIC]
Hi, my name is holl and I am here
to write some php.
You can see my screen, here.
My idea is to explode the whole string by the break, and try to detect which lines which are either empty or start with a number, like so...
$lines = explode("\n", $my_string);
foreach ($lines as $line) {
if (is_numeric(line[0]) || empty(line[0]) ) {
continue;
}
$exclude[] = $line;
}
$transcript = implode("\n", $exclude);
But the result of this action is exactly the same- the output has numbers and blank lines. I clearly misunderstand something- but what is it? And is there a better way of trying to achieve my goal?
Thanks!
EDIT: Removed an echo where I wasn't actually using one in my code.
The problem is that you use indexing on $line:
$lines = explode("\n", $my_string);
foreach ($lines as $line) {
if (is_numeric(line[0]) || empty(line[0]) ) {//index usage?
continue;
}
$exclude[] = $line;
}
$transcript = echo implode("\n", $exclude); //remove echo
replace by:
$lines = explode("\n", $my_string);
foreach ($lines as $line) {
if (is_numeric($line) || empty($line) ) {//here
continue;
}
$exclude[] = $line;
}
$transcript = implode("\n", $exclude);
You also need regex matching to remove the 00:00:00.000 --> 00:00:04.980 fragments.
You can combine them by:
if(preg_match('/^(|\d+|\d+:\d+:\d+\.\d+\s+-->\s+\d+:\d+:\d+\.\d+)$/',$line)) { //regex
takes all possibilities into account:
$lines = explode("\n", $my_string);
foreach ($lines as $line) {
if(preg_match('/^(|\d+|\d+:\d+:\d+\.\d+\s+-->\s+\d+:\d+:\d+\.\d+)$/',$line)) {
continue;
}
$exclude[] = $line;
}
$transcript = implode("\n", $exclude);
echo $transcript;
Example (with php -a):
$ php -a
php > $my_string='1
php ' 00:00:00.000 --> 00:00:04.980
php ' [MUSIC]
php '
php ' 2
php ' 00:00:04.980 --> 00:00:08.120
php ' Hi, my name is holl and I am here
php ' to write some PHP.
php '
php ' 3
php ' 00:00:08.120 --> 00:00:10.277
php ' You can see my screen, here.';
php > $lines = explode("\n", $my_string);
php > foreach ($lines as $line) {
php { if(preg_match('/^(|\d+|\d+:\d+:\d+\.\d+\s+-->\s+\d+:\d+:\d+\.\d+)$/',$line)) {
php { continue;
php { }
php { $exclude[] = $line;
php { }
php > $transcript = implode("\n", $exclude);
php > echo $transcript;
[MUSIC]
Hi, my name is holl and I am here
to write some PHP.
You can see my screen, here.
Your code works almost. Just forgot $ in line[0] and " " is not empty().
$my_string = <<< EOF
1
00:00:00.000 --> 00:00:04.980
[MUSIC]
2
00:00:04.980 --> 00:00:08.120
Hi, my name is holl and I am here
to write some PHP.
3
00:00:08.120 --> 00:00:10.277
You can see my screen, here.
EOF;
$lines = explode("\n", $my_string);
foreach ($lines as $line) {
$temp = trim($line[0]);
if (is_numeric($temp) || empty($temp) ) {
continue;
}
$exclude[] = $line;
}
$transcript = implode("\n", $exclude);
echo $transcript;
Result:
[MUSIC]
Hi, my name is holl and I am here
to write some PHP.
You can see my screen, here.
It looks like it's a pattern. That is every first and second line contain meta data, the third is text, and the fourth is empty. If that is indeed the case, it should be trivial. You don't have to check the content at all and just grab the third line of every quartet:
$lines = explode("\n", $my_string);
$texts = array();
for ($i = 0; $i < count($lines); $i++) {
if ($i % 4 == 2) { // Index of third line is 2, of course.
$texts[] = $lines[i];
}
}
$transcript = implode($texts, "\n");
With alternative logic, because as you rightfully mentioned there can be more than one line of text, you could say that blocks/entries whatever you call them, are separated by an empty line. Each block starts with two lines of meta data, followed by one (or maybe zero) or more lines of text. With that logic you could parse it like this:
$lines = explode("\n", $my_string);
$texts = array();
$linenr = 0;
foreach ($lines as $line) {
// Keep track of the how manieth non-empty line it is.
if ($line === '')
$linenr = 0;
else
$linenr++;
// Skip the first two lines of a block.
if ($linenr > 2)
$texts[] = $line;
}
$transcript = implode($texts, "\n");
I don't know this particular format, but if I wanted to do this, I would be eager to find a pattern like this rather than parse the lines themselves. It looks like a script or subtitle file, and if you want to turn it into a transcript, it would be a shame if somebody shouted '300' and it would not be transcripted.
to remove theses lines try to use : preg_replace + regex
php man [1]: http://php.net/manual/en/function.preg-replace.php

Get value from file - php

Let's say I have this in my text file:
Author:MJMZ
Author URL:http://abc.co
Version: 1.0
How can I get the string "MJMZ" if I look for the string "Author"?
I already tried the solution from another question (Php get value from text file) but with no success.
The problem may be because of the strpos function. In my case, the word "Author" got two. So the strpos function can't solve my problem.
Split each line at the : using explode, then check if the prefix matches what you're searching for:
$lines = file($filename, FILE_IGNORE_NEW_LINES);
foreach($lines as $line) {
list($prefix, $data) = explode(':', $line);
if (trim($prefix) == "Author") {
echo $data;
break;
}
}
Try the following:
$file_contents = file_get_contents('myfilename.ext');
preg_match('/^Author\s*\:\s*([^\r\n]+)/', $file_contents, $matches);
$code = isset($matches[1]) && !empty($matches[1]) ? $matches[1] : 'no-code-found';
echo $code;
Now the $matches variable should contains the MJMZ.
The above, will search for the first instance of the Author:CODE_HERE in your file, and will place the CODE_HERE in the $matches variable.
More specific, the regex. will search for a string that starts with the word Author followed with an optional space \s*, followed by a semicolon character \:, followed by an optional space \s*, followed by one or more characters that it is not a new line [^\r\n]+.
If your file will have dinamically added items, then you can sort it into array.
$content = file_get_contents("myfile.txt");
$line = explode("\n", $content);
$item = new Array();
foreach($line as $l){
$var = explode(":", $l);
$value = "";
for($i=1; $i<sizeof($var); $i++){
$value .= $var[$i];
}
$item[$var[0]] = $value;
}
// Now you can access every single item with his name:
print $item["Author"];
The for loop inside the foreach loop is needed, so you can have multiple ":" in your list. The program will separate name from value at the first ":"
First take lines from file, convert to array then call them by their keys.
$handle = fopen("file.txt", "r");
if ($handle) {
while (($line = fgets($handle)) !== false) {
$pieces = explode(":", $line);
$array[$pieces[0]] = $pieces[1];
}
} else {
// error opening the file.
}
fclose($handle);
echo $array['Author'];

Categories