Skip to content

Commit

Permalink
Merge pull request #6 from clue-labs/unquoted-escapes
Browse files Browse the repository at this point in the history
Support escape sequences in unquoted strings
  • Loading branch information
clue authored Oct 8, 2016
2 parents 2970ede + 7ee541e commit 0083d58
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 21 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,9 @@ way more sophisticated. It also supports parsing the following:
* Single quoted strings (`'hello world'`) which preserve any whitespace characters and
only accept escape sequences `\\` and `\'`, e.g. `'let\'s go'`.
* Double quoted strings (`"hello world"`) which preserve any whitespace characters and
support common escape sequences such as `\t\r\n` etc., e.g. `"hello\nworld!"`.
* Unquoted strings are terminated at the next whitespace character.
support common escape sequences such as `\t\r\n` etc., e.g. `"hi there\nworld!"`.
* Unquoted strings are terminated at the next (unescaped) whitespace character and
support common escape sequences such as `\t\r\n` etc., e.g. `hi\ there\nworld!`.
* Ignores excessive whitespace around arguments, such as trailing whitespace or
multiple spaces between arguments.
* Makes no assumptions about your input encoding, so this works with binary data
Expand Down
35 changes: 16 additions & 19 deletions src/functions.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,19 @@ function split($command)
for (; isset($command[$i]); ++$i) {
$c = $command[$i];

if ($inQuote === '"') {
// we're within a "double quoted" string
if ($inQuote === "'") {
// we're within a 'single quoted' string
if ($c === '\\' && isset($command[$i + 1]) && ($command[$i + 1] === "'" || $command[$i + 1] === '\\')) {
// escaped single quote or backslash ends up as char in argument
$argument .= $command[++$i];
continue;
} elseif ($c === "'") {
// single quote ends
$inQuote = null;
continue;
}
} else {
// we're not within any quotes or within a "double quoted" string
if ($c === '\\' && isset($command[$i + 1])) {
// any escaped character will be processed
$c = $command[++$i];
Expand All @@ -59,29 +70,15 @@ function split($command)
$argument .= $c;
}
continue;
} else if ($c === '"') {
} elseif ($inQuote === '"' && $c === '"') {
// double quote ends
$inQuote = null;
continue;
}
} elseif ($inQuote === "'") {
// we're within a 'single quoted' string
if ($c === '\\' && isset($command[$i + 1]) && ($command[$i + 1] === "'" || $command[$i + 1] === '\\')) {
// escaped single quote or backslash ends up as char in argument
$argument .= $command[++$i];
continue;
} elseif ($c === "'") {
// single quote ends
$inQuote = null;
continue;
}
} else {
// we're not within any quotes
if ($c === '"' || $c === "'") {
} elseif ($inQuote === null && ($c === '"' || $c === "'")) {
// start of quotes found
$inQuote = $c;
continue;
}elseif (in_array($c, $ws)) {
} elseif ($inQuote === null && in_array($c, $ws)) {
// whitespace character terminates unquoted argument
break;
}
Expand Down
14 changes: 14 additions & 0 deletions tests/SplitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,27 @@ public function testSingleStringWithWhitespace()
$this->assertEquals(array('hello'), $args);
}

public function testSingleStringWithEscapedWhitespace()
{
$args = Arguments\split('hello\\ world');

$this->assertEquals(array('hello world'), $args);
}

public function testSimpleStringWithArgument()
{
$args = Arguments\split('hello world');

$this->assertEquals(array('hello', 'world'), $args);
}

public function testSimpleStringWithArgumentWithInterpretedEscape()
{
$args = Arguments\split('hello world\\nthere!');

$this->assertEquals(array('hello', "world\nthere!"), $args);
}

public function testSimpleStringWithArgumentsAndWhitespace()
{
$args = Arguments\split(' hello world ');
Expand Down

0 comments on commit 0083d58

Please sign in to comment.