53

I want to do something like this:

$ [mysql query that produces many lines] | php parse_STDIN.php

In parse_STDIN.php file I want to be able to parse my data line by line from stdin.

Thomas Ayoub
  • 29,063
  • 15
  • 95
  • 142
sobi3ch
  • 2,555
  • 2
  • 31
  • 41
  • Have you tried calling that query from within the PHP script? You know mysqli_query("SELECT `many_lines` FROM `big_table`");? That way, you don't have to pass arguments or anything. PHP is a script language used for webservers. If you want a real processing solution, use a programming language, like C. – ATaylor Aug 15 '12 at 11:11
  • Firstly: why? Why not just run the query in the PHP script? Secondly: `while (!feof(STDIN)) { $line = fgets(STDIN); do_stuff($line); }` – DaveRandom Aug 15 '12 at 11:13
  • You should know about the *Commandline Usage* section in the PHP manual: [Input/output streams](http://php.net/manual/features.commandline.io-streams.php) – hakre Aug 15 '12 at 11:22
  • 1
    @ATaylor because I prefer php then C. I don't see the reasing to hassle with C if I know much better php. – sobi3ch Aug 15 '12 at 14:15
  • @DaveRandom because I want to use it to different things not only to this one mysql query.. – sobi3ch Aug 15 '12 at 14:16
  • @hakra I know, but there is nothing about multi-line reading. – sobi3ch Aug 15 '12 at 14:18

2 Answers2

102

use STDIN constant as file handler.

while($f = fgets(STDIN)){
    echo "line: $f";
}

Note: fgets on STDIN reads the \n character.

Shiplu Mokaddim
  • 56,364
  • 17
  • 141
  • 187
  • 1
    'accept'? what do you mean. Is there should be [accept] button or what? Sorry I'm not using stackoverflow very often so maybe I missing something. – sobi3ch Aug 15 '12 at 16:01
  • This is theoretically incorrect. It won't work for inputs that have empty lines: `echo -e "one\ntwo\n\n\nthree\n" | php readFromStdin.php`. Check my edit. – yourdeveloperfriend Dec 17 '14 at 19:20
  • 1
    @yourdeveloperfriend What do you mean by `wont't work`? If the line is empty it'll read empty string. Check this [ideone](http://ideone.com/PWQHhG) – Shiplu Mokaddim Dec 17 '14 at 20:20
  • 5
    In case anyone else was slow to understand like me, "fgets on STDIN reads the `\n` character" means "the string in `$f` will include the `\n` character". I.e. the newline is included in the return value from `fgets` (see http://php.net/fgets) – Sam Jun 22 '15 at 15:51
15

You could also use a generator - if you don't know how large the STDIN is going to be.

Requires PHP 5 >= 5.5.0, PHP 7

Something along the lines of:

function stdin_stream()
{
    while ($line = fgets(STDIN)) {
        yield $line;
    }
}

foreach (stdin_stream() as $line) {
    // do something with the contents coming in from STDIN
}

You can read more about generators here (or a google search for tutorials): http://php.net/manual/en/language.generators.overview.php

Luis Colón
  • 195
  • 1
  • 5
  • what if some line in STDIN will be empty or `"0"`? – luchaninov Sep 27 '16 at 11:30
  • 2
    Since `fgets()` keeps the newline at the end ("\n"), that won't happen until EOF. – MatsLindh Jul 26 '17 at 13:48
  • you can do `if(!defined("STDIN")) define("STDIN", "fopen('php://stdin','r')");` on lower php-versions – Radon8472 May 01 '18 at 20:18
  • 2
    This implementation is over-complicated and unnecessary abstraction. Whatever is done within the foreach could just as simply be done in the while loop. – Matthew Haworth Oct 12 '18 at 09:05
  • If used as written I agree the script is needlessly complicated, but in general separating out the foreach and the fgets into separate parts of the program could be helpful. For instance it would allow writing a test that passes a hard-coded array of lines to the function that does the foreach to check it returns the right results. – bdsl Apr 13 '19 at 18:38