问题:给定一个文件名和一个任意的字符串列表,是否有一种 * 规范的方式 * 来创建一个命令行,使Environment.GetCommandLineArgs(以及C#的void main(String[] args)
/ VB的Sub Main(args() As String)
)返回相同的字符串列表?
背景:.NET将命令行拆分为参数的方式是surprisingly complex,例如:
如果双引号跟在两个或偶数个反斜杠之后,则前面的每对反斜杠都将被一个反斜杠替换,并删除双引号。如果双引号跟在奇数个反斜杠之后,其中只有一个反斜杠,则前面的每对反斜杠都将被一个反斜杠替换,并删除剩余的反斜杠;但是,在这种情况下,双引号不会被删除。
许多人尝试简单的“将每个参数放在双引号中并转义现有的双引号”方法,并且一旦其中一个参数包含尾随反斜杠就会失败。关于这个问题,StackOverflow上有各种各样的问题,例如:
- How to escape path containing spaces
- Escape command line arguments in c#
- Escape string for Process.Start
- Passing command-line arguments in C#
然而,他们的答案要么不够通用,无法为所有情况提供规范的解决方案,要么似乎是“迭代”开发的(“哦,还有一个特殊情况我忘了,让我们添加它,现在它应该涵盖大多数情况......”)。
- 来自权威来源(可能是参与这个疯狂的命令行约定的开发人员之一的博客条目)或
- 提供给定算法满足.NET命令行要求的正式证明。
3条答案
按热度按时间ltskdhd11#
This algorithm是通用的,来自相对权威的来源(MSDN博客)。
v2g6jxz62#
几年前,微软宣布他们将在CodePlex上发布一个命令行解析器(而不是.NET Framework 4附带的System.Shell.CommandLine)。我不确定他们是否真的这么做了。如果你想让微软员工开发一个解析器,可以看看cmdline。你也可以在CodePlex中查找命令行解析器。
你也可以试试Mono.Options,它非常强大。
a64a0gku3#
从.NET Core 2.1开始,不再需要手动转义命令行参数:
ProcessStartInfo
现在有一个ArgumentList
属性,并自动处理任何需要的转义。引用the documentation的例子:
在这里你可以看到算法的全部荣耀(包括著名的“2n+1反斜杠规则”)。它是MIT许可的,这使得它很容易在需要的时候反向移植到.NET Framework 4.8项目。