Skip to content

Instantly share code, notes, and snippets.

@FLamparski
Created January 27, 2017 15:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FLamparski/104407d41322e47f766d4aba7bf2a20e to your computer and use it in GitHub Desktop.
Save FLamparski/104407d41322e47f766d4aba7bf2a20e to your computer and use it in GitHub Desktop.
Hacky way to use shlex.split in PHP
<?php
/**
* Hacks around the fact that there isn't a good shell-style argument lexer
* for PHP by using the Python one.
* One argument: the line to parse as a shell line.
* Returns: An array such that:
* 'foo --bar baz\ foo "/bar/foo man/quux"' → ['foo', '--bar', 'baz foo', '/bar/foo man/quux']
* Caveat: no error handling. Depends on /usr/bin/python3 being python. It's horrible.
*/
function hack_shlex($str) {
// Set up file descriptors for the python program
$dspec = [
0 => ['pipe', 'r'],
1 => ['pipe', 'w'],
2 => ['file', '/dev/null', 'a']
];
// Opens Python, it runs the following program:
//
// from shlex import split
// from json import dumps
// print(dumps(split(input())))
//
// It does exactly 4 things:
// 1. Reads a line from the standard input
// 2. Uses the Python shlex module to parse the line into shell arguments
// 3. Encodes the resulting array of strings into JSON
// 4. Prints that JSON to stdout, to be read from the PHP side.
$ph = proc_open("/usr/bin/python3 -c 'from shlex import split; from json import dumps; print(dumps(split(input())));'", $dspec, $pipes);
// Writes the string to lex to the python program
fwrite($pipes[0], $str);
// Close the write stream as we've written what we needed
fclose($pipes[0]);
// Read the result from the Python program
$result = stream_get_contents($pipes[1]);
// No need for this now
fclose($pipes[1]);
// Python's done its job now
proc_close($ph);
// Decode json and return the parsed shell line
return json_decode(trim($result));
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment