我有一个Powershell脚本(作为其中一个选项)从文件中读取用户定义的预执行命令,并需要执行它。 用户定义的预执行命令应该是普通的DOS样式命令。 我可以用空格分割命令,然后将它提供给PowerShell“&”执行它:
"C:\Program Files\Tool\program1" 25 "the quick brown fox"
但是如果用户定义的命令字符串有空格需要进入参数,或者命令的路径有空格,那么我需要更聪明地解析用户定义的字符串。
肉眼很明显,以下字符串在前面有一个命令后跟2个参数:
{{1}}
是否有人已经有一个函数可以解析这样的字符串并返回一个DOS样式命令的数组或列表以及每个参数?
答案 0 :(得分:2)
有一个非常简单的解决方案。您可以滥用Powershell参数解析机制:
> $paramString = '1 blah "bluh" "ding dong" """foo"""'
> $paramArray = iex "echo $paramString"
> $paramArray
1
blah
bluh
ding dong
"foo"
答案 1 :(得分:0)
最后我使用CommandLineToArgvW()来解析命令行。 有了这个,我可以在需要时将双引号字面地传递给参数,并且在双引号参数中有空格。 e.g:
abc def
23
"z"
成为具有3个参数的目录命令:
function Split-CommandLine
{
<#
.Synopsis
Parse command-line arguments using Win32 API CommandLineToArgvW function.
.Link
https://github.com/beatcracker/Powershell-Misc/blob/master/Split-CommandLine.ps1
http://edgylogic.com/blog/powershell-and-external-commands-done-right/
.Description
This is the Cmdlet version of the code from the article http://edgylogic.com/blog/powershell-and-external-commands-done-right.
It can parse command-line arguments using Win32 API function CommandLineToArgvW .
.Parameter CommandLine
A string representing the command-line to parse. If not specified, the command-line of the current PowerShell host is used.
#>
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, Position=0)]
[ValidateNotNullOrEmpty()]
[string]$CommandLine
)
Begin
{
$Kernel32Definition = @'
[DllImport("kernel32")]
public static extern IntPtr LocalFree(IntPtr hMem);
'@
$Kernel32 = Add-Type -MemberDefinition $Kernel32Definition -Name 'Kernel32' -Namespace 'Win32' -PassThru
$Shell32Definition = @'
[DllImport("shell32.dll", SetLastError = true)]
public static extern IntPtr CommandLineToArgvW(
[MarshalAs(UnmanagedType.LPWStr)] string lpCmdLine,
out int pNumArgs);
'@
$Shell32 = Add-Type -MemberDefinition $Shell32Definition -Name 'Shell32' -Namespace 'Win32' -PassThru
}
Process
{
$ParsedArgCount = 0
$ParsedArgsPtr = $Shell32::CommandLineToArgvW($CommandLine, [ref]$ParsedArgCount)
Try
{
$ParsedArgs = @();
0..$ParsedArgCount | ForEach-Object {
$ParsedArgs += [System.Runtime.InteropServices.Marshal]::PtrToStringUni(
[System.Runtime.InteropServices.Marshal]::ReadIntPtr($ParsedArgsPtr, $_ * [IntPtr]::Size)
)
}
}
Finally
{
$Kernel32::LocalFree($ParsedArgsPtr) | Out-Null
}
$ret = @()
# -lt to skip the last item, which is a NULL ptr
for ($i = 0; $i -lt $ParsedArgCount; $i += 1) {
$ret += $ParsedArgs[$i]
}
return $ret
}
}
$executionCommand = Get-Content .\commands.txt
$executionArgs = Split-CommandLine $executionCommand
$executionCmd = $executionArgs[0]
$executionNumArgs = $executionArgs.Length - 1
if ($executionNumArgs -gt 0) {
$executionArgs = $executionArgs[1..$executionNumArgs]
echo $executionCmd $executionArgs
& $executionCmd $executionArgs
} else {
echo $executionCmd
& $executionCmd
}
代码是:
<?php
if (ob_get_level() == 0) ob_start();
for ($i = 0; $i<10; $i++){
echo "<br> Line to show.";
echo str_pad('',4096)."\n";
ob_flush();
flush();
}
echo "Done.";
ob_end_flush();
?>
答案 2 :(得分:0)
function ParseCommandLine($commandLine)
{
return Invoke-Expression ".{`$args} $commandLine"
}