quick question really.
Consider the following code:
//__/var/test/cli_test.php__
$x = 0;
while ($x < 9){
print "loop " . str_pad($x, 3, "0", STR_PAD_LEFT) . "\n";
sleep(1);
$x++;
}
if I type php /var/test/cli_test.php in the command line I get 9 interspaced-by-time lines.. i.e. 9 positive outputs, one per second. EG: these arrive one at a time, blip blip blip...
loop 000
loop 001
loop 002
loop 003
loop 004
loop 005
loop 006
loop 007
loop 008
now consider a different proposition
//__/var/test/cli_test_shell.php
print shell_exec("php /var/test/cli_test.php");
if I type php /var/test/cli_test_shell.php in the command line I get nothing for 9 seconds then everything arrives.. i.e. 1 BIG output 1 BIG wait. after 9 seconds of nothing EG: wait, wait wait.. nothing THEN DUMP:
loop 000
loop 001
loop 002
loop 003
loop 004
loop 005
loop 006
loop 007
loop 008
how can I alter /var/test/cli_test_shell.php so that the output returns each line on per second
try this:
$handle = popen('php /var/test/cli_test_shell.php 2>&1', 'r');
while (!feof($handle)) {
echo fread($handle, 8192);
}
fclose($handle);
The desired behaviour is not possible using shell_exec(). This is because the function collects the output of the command and returns it as a string - after the command's termination. Use passthru() instead and keep cli_test.php as it is.
Related
#!/usr/bin/php
<?php
define("KPA_PEOPLE","/devel/pic/snk_db2/KPA-migration/Keywords/gettingTheKeywordsAndFiles/KPA_People.txt");
$hndl_kpa_people=fopen(KPA_PEOPLE,"r+") or die("Failed opening ".KPA_PEOPLE);
while($line=fgets($hndl_kpa_people)!==FALSE){
echo "\nline: ".$line."\n";
}
?>
Context:
The file looks like this in the file system:
-rw-r--r-- 1 snkdb snkdb 6096 dec 25 14:08 KPA_People.txt
(I'm the user snkdb)
The file's contents looks like:
et|2
Elisabet|3
okända|4...
The result looks like:
line: 1
line: 1
line: 1...
the expected result was:
et|2
Elisabet|3
okända|4...
as far as I understand the "while($line=fgets($hndl_kpa_people)!==FALSE)"
follows the convention in the manual and looks like it works in earlier scripts.
Any thoughts would be appreciated!
In the following line:
while($line=fgets($hndl_kpa_people)!==FALSE)
PHP is first evaluating the expression fgets($hndl_kpa_people)!==FALSE and then assigns it to the variable $line.
Furthermore, it is redundant to evaluate if something inside the while loop is different from false, since while loop runs while the condition it's evaluating is true.
So the line should be:
while($line = fgets($hndl_kpa_people))
You can read more on Operator Precedence in the official documentation: https://www.php.net/manual/en/language.operators.precedence.php
You can read more about while loop here: https://www.php.net/manual/en/control-structures.while.php
Edit: Since there is a confusion in the comments whether reading an empty line will return false - it will not. Take the following simple example:
<?php
$file = fopen('sample.txt', "r+");
$counter = 0;
while ($line = fgets($file)) {
print_r("Counter: $counter - Line: " . $line);
$counter++;
}
fclose($file);
with the following sample file:
test 123
test 234
test 345
The result from execution is:
Counter: 0 - Line: test 123
Counter: 1 - Line:
Counter: 2 - Line: test 234
Counter: 3 - Line: test 345
I want to get my output like this
1 5 9 13
2 6 10 14
3 7 11 15
4 8 12 16
I am trying like this:
<?php
for($a=1; $a<=16; $a++)
{
for($b=$a; $b>=1; $b--)
{
echo "$b";
}
echo "<br>";
}
?>
The above code gives me the wrong output.
Let's debug.
You are starting from 1 in your outer loop and in your inner loop, you are going from $a till 1 times.
This doesn't comply with your requirements because we have to print an increasing sequence in each row.
You can also notice that every number in a row differs by 4.
So, logic would be like below:
Pseudocode:
rows = 4
starting_number = 1
loop from 1 to rows
number = starting_number
loop from 1 to 4 // since each row has 4 numbers
print number
number += 4
print new_line
starting_number++
Demo: https://3v4l.org/9YjIP
I have a php (v. 7.0.16) script running on the command line with this:
$ct = 1;
foreach($sort_this as $cur_site_id => $dx){
$cur_location = $locations[$cur_site_id]['location'];
$msg = "\033[A\33[2K\r" . 'getting data for %25s (' . $cur_site_id . ') store: %7s %01.2f' . "\n";
echo printf($msg, $cur_location, ($ct . ' / ' . count($sort_this)), number_format((($ct / count($sort_this)) * 100), 2));
$ct++;
}
This loop runs about 40 iterations. The printf statement works with 1 small problem. On the line after the "getting data" line I see a number that increments from 7x-7y as it runs (sometimes it starts at 71, sometimes at 77, etc.). I can't figure out what's causing this number to be printed. So when the loop starts I see something like this on the screen:
getting data for DENVER (531) store: 42 / 42 0.00
77
and when it finishes something like this:
getting data for SEATTLE (784) store: 42 / 42 100.00
79
I found how to print to the same line and clear the data here:
Erase the current printed console line
Is there a way to prevent the 7x codes from showing? Also, what are they?
The problem is on this line:
echo printf(...)
printf() generates a string using its arguments (format and values) and prints it. It returns the number of printed characters (the length of the string it generated).
Your code then passes this value to echo that prints it. This is the source of the extra number in the range of 70-77.
You should either remove the echo or use sprintf() instead of printf().
sprintf() generates the string the same was printf() does but it doesn't print it; it returns it and it is passed as argument to echo that displays it.
printf() returns the length of the outputted string.
See PHP docs:
Return Values: Returns the length of the outputted string.
Just remove echo fom that line.
I need to transpose some values in some csv files that we get sent on a regular basis so that they are able to be imported into a website and I'm not sure the best way to go about doing it.
The data arrives in a csv file with a header row containing the column names, and the first column values are product ID's. The data looks like this…
ID F F-VF VF VF-XF XF
1 840 960 1080 1248 1944
2 1137.5 1300 1462.5 1690 2632.5
3 1225 1400 1575 1820 2835
What I'm looking to do is change this around so the column name and it's value are put into a new line for each value for the same id like so…
ID COND VALUE
1 F 840
1 F-VF 960
1 VF 1080
1 VF-XF 1248
1 XF 1944
2 F 1137.5
2 F-VF 1300
2 VF 1462.5
2 VF-XF 1690
2 XF 2835
I may also need to add some strings into the cells - is that easy to do?
Thanks a lot
Not necessarily the most elegant version, just to get an idea.
Something like this would work in case it's a existing csv, which gets read and overwritten with the transposed version.
// assuming a dataset like
// ----
// fruit, apple, pear, peach
// animal, eagle, bear, wolf
// car, renault, fiat, nio
$f = fopen($savePath, 'r');
$header = [];
$data = [];
while($row = fgetcsv($f, 0, ",")) {
$header[]=$row[0];
for ($i = 1; $i < sizeof(array_keys($row)); $i++) {
$data[$i][$row[0]]=$row[$i];
}
}
fclose($f);
$f = fopen($savePath, 'w');
fputcsv($f, $header);
foreach ($data as $recordColDataSet) {
fputcsv($f, array_values($recordColDataSet));
}
fclose($f);
Transposing arrays could also be something to look at eg in this question here:
Transposing multidimensional arrays in PHP
Have you tried any of the standard PHP methods like: str_getcsv() or fgetcsv()?
A quick search of "php csv" provides a TON of possible solutions. I suggest trying a few, then reporting back here if you have a specific problem.
So, say you have a php post script that appends whatever you pass to it to a text file as a new line
Let say the file is called file.txt and looks like this:
11:45 Am
12:49 PM
Went to Lunch
3:25 PM
I wanna know, how can I write a php script that treats information as pairs of 3.
so in a for loop it would display
line1 | line2 | line3
line4
Notice that there is nothing past line4, so it stopped.
You can use (demo)
$chunksOfThree = array_chunk(file('/path/to/file', FILE_IGNORE_NEW_LINES), 3);
foreach ($chunksOfThree as $chunk) {
echo implode(' | ', $chunk), PHP_EOL;
}
This will output the desired
11:45 Am | 12:49 PM | Went to Lunch
3:25 PM
See the Manual entries for
file — Reads entire file into an array and
array_chunk — Split an array into chunks
implode — Join array elements with a string
fgets reads an entire line from the file. It is slower than something like fread but does what you want.
You can also use the file function to read the whole file into an array. Each element in the array corresponds to a line in the file.
If the number of lines read is not a multiple of 3, just ignore the last 1 or 2 lines.
fgets returns false if there is no more data so you can check that to determine if one of the triplet entries is incomplete.
while(!feof($fp)) {
$line1 = fgets($fp);
$line2 = fgets($fp);
$line3 = fgets($fp);
if ($line2 === false) {
echo "$line1";
} else if ($line3 == false) {
echo "$line1 | $line2";
} else {
echo "$line1 | $line2 | $line3\n";
}
You can use this code for this
<?php
$filename = "test.txt";
$fp = fopen( $filename, "r" ) or die("Couldn't open $filename");
$i=0;
while ( ! feof( $fp ) ) {
$line = fgets( $fp, 1024 );
if($i==2)
{
print "$line";
$i=0;
print "<br>";
}
else
{
print "$line | ";
$i++;
}
}
?>
Output :
11:45 Am | 12:49 PM | Went to Lunch
3:25 PM |