Why does trailing backslash followed by quote beha

2019-06-06 21:16发布

With this program (cs.exe):

class Program
{
    static void Main(string[] args)
    {
        foreach (var item in args)
        {
            Console.WriteLine(item);
        }
    }
}

And run:

> cs.exe go\to\a_path
go\to\a_path

> cs.exe "go\to\a path"
go\to\a path

> cs.exe "go\to\a path\"
go\to\a path"

> cs.exe 'go\to\a path\'
'go\to\a
path\'

That means if your path has a space so you quote it, be very careful NOT to put a trailing \ at the end, otherwise your program might just not be able to handle it as it incorrectly contains a " at the end. Single quote is even weirder!

PowerShell exhibits a similar behavior but without the difference between single and double quotes.

How do I understand this behavior? What's the underlying rule to evaluate backslash in cmd so this can be explained consistently?

标签: windows cmd
1条回答
劳资没心,怎么记你
2楼-- · 2019-06-06 21:44

As you are not calling an internal cmd command, but calling an executable file, this behaviour is not caused by cmd but the command line argument parser routines. In windows, programs don't receive a collection/array/set of arguments, but a string with all the arguments and each program tokenizes this string to obtain each element. This is usually done by routines included by the compiler that hides this operation and exposes to the code an easier way to handle arguments.

Documentation for the C Command-Line argument parser states that

  • Arguments are delimited by white space, which is either a space or a tab.

  • A string surrounded by double quotation marks is interpreted as a single argument, regardless of white space contained within. A quoted string can be embedded in an argument. Note that the caret (^) is not recognized as an escape character or delimiter.

  • A double quotation mark preceded by a backslash, \", is interpreted as a literal double quotation mark (").

  • Backslashes are interpreted literally, unless they immediately precede a double quotation mark.

  • If an even number of backslashes is followed by a double quotation mark, then one backslash (\) is placed in the argv array for every pair of backslashes (\\), and the double quotation mark (") is interpreted as a string delimiter.

  • If an odd number of backslashes is followed by a double quotation mark, then one backslash (\) is placed in the argv array for every pair of backslashes (\\) and the double quotation mark is interpreted as an escape sequence by the remaining backslash, causing a literal double quotation mark (") to be placed in argv.

There is also a set of undocumented/non official rules (How Command Line Parameters Are Parsed)

  • Outside a double quoted block a " starts a double quoted block.
  • Inside a double quoted block a " followed by a different character (not another ") ends the double quoted block.
  • Inside a double quoted block a " followed immediately by another " (i.e. "") causes a single " to be added to the output, and the double quoted block continues.

The .Net argument parsing rules are just a derivation of those rules. If you need a different behaviour, then you should use the Environment.CommandLine property to retrieve the full command line string and write your own parsing code.

查看更多
登录 后发表回答