问题:给定文件名和任意字符串列表,是否有规范的方式创建单个命令行,使得Environment.GetCommandLineArgs(和C#的
void main(String[] args)
/ VB的Sub Main(args() As String)
)将返回相同的字符串列表?
背景:.NET 将命令行拆分为参数的方式出奇地复杂,例如:
如果双引号跟在两个或偶数个反斜杠之后,则每个前面的反斜杠对都将替换为一个反斜杠,并删除双引号。如果双引号后面有奇数个反斜杠,包括一个,前面的每一对都被一个反斜杠替换,剩下的反斜杠被删除;但是,在这种情况下,双引号没有被删除。
许多人尝试简单的“将每个参数放在双引号中并转义现有的双引号”方法,并且一旦其中一个参数包含尾部反斜杠就会失败。关于这个问题,StackOverflow 上有各种问题,例如:
但是,他们的答案要么不够笼统,无法为所有情况提供规范的解决方案,要么似乎是“迭代”开发的(“哦,我忘了还有一个特殊情况,让我们添加它,现在它应该涵盖大多数情况...”)。由于这是一个很常见的问题,我希望看到一个提供信心的解决方案,例如,通过 either
这个算法是通用的,来自比较权威的来源(MSDN博客)
几年前,Microsoft 宣布他们将在 CodePlex 上发布命令行解析器(而不是本应随 .NET Framework 4 一起提供的 System.Shell.CommandLine)。我不确定他们是否真的这样做了。如果您想要 Microsoft 员工开发的解析器,请查看 cmdline。您也可以在 CodePlex.
中查找命令行解析你也可以尝试 Mono.Options 这非常强大。
从 .NET Core 2.1 开始,不再需要手动转义命令行参数:
ProcessStartInfo
现在有一个 ArgumentList
属性并自动处理任何需要的转义。
引用文档中的例子:
var info = new System.Diagnostics.ProcessStartInfo("cmd.exe");
info.ArgumentList.Add("/c");
info.ArgumentList.Add("dir");
info.ArgumentList.Add(@"C:\Program Files\dotnet");
在这里您可以看到该算法的所有优点(包括著名的“2n+1 反斜杠规则”)。它是 MIT 许可的,如果需要,这使得它很容易向后移植到 .NET Framework 4.8 项目。