Reputation: 14705
How is it possible to split this string:
$Arguments = '/NOGUI /DATE /EXPAND 4 /SIZEUNIT 3 /SORTTYPE 0 /EXCEL "S:\Test\Brecht\Log Test\Report 13.xlsx" /SHEETNAME "Data set" /SCANPATH "S:\My Folder"'
into the following array:
/NOGUI
/DATE
/EXPAND
4
/SIZEUNIT
3
/SORTTYPE
0
/EXCEL
"S:\Test\Brecht\Log Test\Report 13.xlsx"
/SHEETNAME
"Data set"
/SCANPATH
"S:\My Folder"
When using $Argument.split(' ')
it also splits the double quoted strings, which is not desired. On the ScriptingGuy's blog, they explain what is possible. But I can't seem to find a way to ignore the strings between double quotes.
Upvotes: 3
Views: 3071
Reputation: 437558
Given that your string is a list of arguments that is (also) syntax-compatible with command calls in cmd.exe
, a pragmatic solution is to pass your string to cmd /c
and take advantage of cmd.exe
's ability to splits such lists into individual arguments via its internal for
statement:
$ArgumentList =
'/NOGUI /DATE /EXPAND 4 /SIZEUNIT 3 /SORTTYPE 0 /EXCEL "S:\Test\Brecht\Log Test\Report 13.xlsx" /SHEETNAME "Data set" /SCANPATH "S:\My Folder"'
cmd /c "for %i in ($ArgumentList) do @echo %i"
Since PowerShell captures output from external-program calls line by line, assigning the result to a variable will automatically create an array of individual arguments - with "..."
enclosures retained, as requested.
Note:
cmd.exe
, the above would expand cmd.exe
-style variable references such as %USERPROFILE%
and would only recognize ""
as an escaped "
inside a "..."
argument.If, by contrast, the argument list is to be interpreted as one for PowerShell, you can employ an analogous technique with Write-Output
and Invoke-Expression
, though note that the latter is generally best avoided unless you fully control or implicitly trust the string being evaluated.
$ArgumentList =
'/NOGUI /DATE /EXPAND 4 /SIZEUNIT 3 /SORTTYPE 0 /EXCEL "S:\Test\Brecht\Log Test\Report 13.xlsx" /SHEETNAME "Data set" /SCANPATH "S:\My Folder"'
Invoke-Expression "Write-Output -- $ArgumentList"
Note:
Caveat: Due to interpretation by PowerShell, $
-prefixed tokens are expanded, as are any embedded commands, whether enclosed in $(...)
or just (...)
, and PowerShell's string-literal rules apply, so that both ""
and `"
- but not \"
- are recognized as escaped "
chars. inside "..."
arguments.
This solution invariably removes any enclosing "..."
from the individual arguments.
Finally, to offer concise solution based on PowerShell's regex-based -split
and -match
operators (and a verbatim here-string to provide the input):
$ArgumentList =
'/NOGUI /DATE /EXPAND 4 /SIZEUNIT 3 /SORTTYPE 0 /EXCEL "S:\Test\Brecht\Log Test\Report 13.xlsx" /SHEETNAME "Data set" /SCANPATH "S:\My Folder"'
$ArgumentList -split '(".*?"|\S+)' -match '\S'
Note:
With this simple approach, tokens with escaped, embedded "
(e.g., "Nat ""King"" Cole"
, "Nat `"King`" Cole"
or "Nat \"King\" Cole"
) are not supported.
As requested in your question, the enclosing "
characters are retained in the elements of the result array.
'"(.*?)"|(\S+)'
instead, but note that the solution will then also eliminate any ""
tokens from the result array.
-replace '"(.*?)"', '$1'
after -match '\S'
'For an explanation of the approach see this answer to a related question in the context of also supporting single-quoted tokens.
Upvotes: 0
Reputation: 27423
Trying to match each element instead, based on [RESOLVED] Regex Split on Whitespace EXCEPT in single quotes-VBForums. So anything between double-quotes or non-whitespace. The -match operator can't do allmatches.
$Arguments | select-string '("[^"]*"|\S)+' -AllMatches | % matches | % value
/NOGUI
/DATE
/EXPAND
4
/SIZEUNIT
3
/SORTTYPE
0
/EXCEL
"S:\Test\Brecht\Log Test\Report 13.xlsx"
/SHEETNAME
"Data set"
/SCANPATH
"S:\My Folder"
You might need to delete the quotes:
$list = $list -replace '"'
Upvotes: 3
Reputation: 506
$Arguments = '/NOGUI /DATE /EXPAND 4 /SIZEUNIT 3 /SORTTYPE 0 /EXCEL "S:\Test\Brecht\Log Test\Report 13.xlsx" /SHEETNAME "Data set" /SCANPATH "S:\My Folder"'
$splitString = [regex]::Split( $Arguments, ' (?=(?:[^"]|"[^"]*")*$)' )
$splitString
Output:
/NOGUI
/DATE
/EXPAND
4
/SIZEUNIT
3
/SORTTYPE
0
/EXCEL
"S:\Test\Brecht\Log Test\Report 13.xlsx"
/SHEETNAME
"Data set"
/SCANPATH
"S:\My Folder"
Upvotes: 10