user151841
user151841

Reputation: 18056

piping data into command line php?

It is possible to pipe data using unix pipes into a command-line php script? I've tried

$> data | php script.php

But the expected data did not show up in $argv. Is there a way to do this?

Upvotes: 37

Views: 34440

Answers (10)

NVRM
NVRM

Reputation: 13162

It can be fed by the STDIN as well.

php <<< 'Hi <?php echo getenv()["USER"];?>!'

echo 'Hi <?php echo getenv()["USER"];?>!' | php

Feeding a file into the STDIN:

cat code.php | php

php <<< $(cat somecool.php)

php < somecool.php

However passing strings to the shell will cause issues with some Unicode characters and may cause shell related annoyances. To avoid that, use a string encoded in base64:

system("echo '$base64String' | base64 --decode | php");

Upvotes: 0

Richard A Quadling
Richard A Quadling

Reputation: 4008

I needed to take a CSV file and convert it to a TSV file. Sure, I could import the file into Excel and then re-export it, but where's the fun in that when piping the data through a converter means I can stay in the commandline and get the job done easily!

So, my script (called csv2tsv) is

#!/usr/bin/php
<?php
while(!feof(STDIN)){
    echo implode("\t", str_getcsv(fgets(STDIN))), PHP_EOL;
}

I chmod +x csv2tsv.

I can then run it cat data.csv | csv2tsv > data.tsv and I now have my data as a TSV!

OK. No error checking (is the data an actual CSV file?), etc. but the principle works well.

And of course, you can chain as many commands as you need.

If you are wanting more to expand on this idea, then how about the ability to include additional options to your command?

Simple!

#!/usr/bin/php
<?php
$separator = $argv[1] ?? "\t";
while(!feof(STDIN)){
    echo implode($separator, str_getcsv(fgets(STDIN))), PHP_EOL;
}

Now I can overwrite the default separator from being a tab to something else. A | maybe!

cat data.csv | csv2tsv '|' > data.psv

Hope this helps and allows you to see how much more you can do!

Upvotes: 1

hawken
hawken

Reputation: 661

PHP can read from standard input, and also provides a nice shortcut for it: STDIN.

With it, you can use things like stream_get_contents and others to do things like:

$data = stream_get_contents(STDIN);

This will just dump all the piped data into $data.

If you want to start processing before all data is read, or the input size is too big to fit into a variable, you can use:

while(!feof(STDIN)){
    $line = fgets(STDIN);
}

STDIN is just a shortcut of $fh = fopen("php://stdin", "r");. The same methods can be applied to reading and writing files, and tcp streams.

Upvotes: 56

Nadir
Nadir

Reputation: 715

Best option is to use -r option and take the data from the stdin. Ie I use it to easily decode JSON using PHP. This way you don't have to create physical script file.

It goes like this:

docker inspect $1|php -r '$a=json_decode(stream_get_contents(STDIN),true);echo str_replace(["Array",":"],["Shares","  -->  "],print_r($a[0]["HostConfig"]["Binds"],true));'

This piece of code will display shared folders between host & a container. Please replace $1 by the container name or put it in a bash alias like ie displayshares() { ... }

Upvotes: 1

giblfiz
giblfiz

Reputation: 211

If your data is on one like, you can also use either the -F or -R flag (-F reads & executes the file following it, -R executes it literally) If you use these flags the string that has been piped in will appear in the (regular) global variable $argn

Simple example:

echo "hello world" | php -R 'echo str_replace("world","stackoverflow", $argn);'

Upvotes: 21

stephenspann
stephenspann

Reputation: 1843

Came upon this post looking to make a script that behaves like a shell script, executing another command for each line of the input... ex:

ls -ln | awk '{print $9}'

If you're looking to make a php script that behaves in a similar way, this worked for me:

#!/usr/bin/php
<?php

$input = stream_get_contents(fopen("php://stdin", "r"));

$lines = explode("\n", $input);

foreach($lines as $line) {
    $command = "php next_script.php '" . $line . "'";
    $output = shell_exec($command);
    echo $output;
}

Upvotes: 3

klokop
klokop

Reputation: 2410

This worked for me:

stream_get_contents(fopen("php://stdin", "r"));

Upvotes: 4

user914330
user914330

Reputation: 78

If you want it to show up in $argv, try this:

echo "Whatever you want" | xargs php script.php

That would covert whatever goes into standard input into command line arguments.

Upvotes: 2

Frank Farmer
Frank Farmer

Reputation: 39386

You can pipe data in, yes. But it won't appear in $argv. It'll go to stdin. You can read this several ways, including fopen('php://stdin','r')

There are good examples in the manual

Upvotes: 4

Gustav Larsson
Gustav Larsson

Reputation: 8497

As I understand it, $argv will show the arguments of the program, in other words:

php script.php arg1 arg2 arg3

But if you pipe data into PHP, you will have to read it from standard input. I've never tried this, but I think it's something like this:

$fp = readfile("php://stdin");
// read $fp as if it were a file

Upvotes: 29

Related Questions