在 Windows 中转义空格
Escaping Spaces in Windows
我在 Linux 环境中积累了很多经验,但现在我需要在 Windows 中做一些事情。我在弄清楚如何在 windows 命令环境中正确转义空格时遇到了一些麻烦。关于它如何解析命令的规则完全不清楚。
例如,在Linux环境中,我可以创建以下脚本:
我的command.sh
#!/bin/bash
echo "Called as '[=11=]' with argument ''"
并像这样执行它,所有可能的转义空格的方法都是等价的。
[bradworkubuntu:~/command_test] my\ command.sh arg\ with\ spaces
Called as './my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] "my command.sh" arg\ with\ spaces
Called as './my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] my\ command.sh "arg with spaces"
Called as './my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] "my command.sh" "arg with spaces"
Called as './my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] /home/brichardson/command_test/my\ command.sh arg\ with\ spaces
Called as '/home/brichardson/command_test/my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] "/home/brichardson/command_test/my command.sh" arg\ with\ spaces
Called as '/home/brichardson/command_test/my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] "/home/brichardson/command_test/my command.sh" "arg with spaces"
Called as '/home/brichardson/command_test/my command.sh' with argument 'arg with spaces'
但是当我在 Windows 上尝试类似的东西时,结果完全不一致。
我的command.bat
echo "Called as '%0' with argument '%1'"
像这样执行:
C:\Users\brichardson\Documents\command_test>my^ command.bat arg^ with^ spaces
'my' is not recognized as an internal or external command,
operable program or batch file.
C:\Users\brichardson\Documents\command_test>"my command.bat" arg^ with^ spaces
C:\Users\brichardson\Documents\command_test>echo "Called as '"my command.bat"' with argument 'arg'"
"Called as '"my command.bat"' with argument 'arg'"
C:\Users\brichardson\Documents\command_test>my^ command.bat "arg with spaces"
'my' is not recognized as an internal or external command,
operable program or batch file.
C:\Users\brichardson\Documents\command_test>"my command.bat" "arg with spaces"
C:\Users\brichardson\Documents\command_test>echo "Called as '"my command.bat"' with argument '"arg w
ith spaces"'"
"Called as '"my command.bat"' with argument '"arg with spaces"'"
C:\Users\brichardson\Documents\command_test>\Users\brichardson\Documents\command_test\my^ command.ba
t arg^ with^ spaces
'\Users\brichardson\Documents\command_test\my' is not recognized as an internal or external command,
operable program or batch file.
C:\Users\brichardson\Documents\command_test>"\Users\brichardson\Documents\command_test\my command.ba
t" arg^ with^ spaces
C:\Users\brichardson\Documents\command_test>echo "Called as '"\Users\brichardson\Documents\command_t
est\my command.bat"' with argument 'arg'"
"Called as '"\Users\brichardson\Documents\command_test\my command.bat"' with argument 'arg'"
C:\Users\brichardson\Documents\command_test>"\Users\brichardson\Documents\command_test\my command.ba
t" "arg with spaces"
C:\Users\brichardson\Documents\command_test>echo "Called as '"\Users\brichardson\Documents\command_t
est\my command.bat"' with argument '"arg with spaces"'"
"Called as '"\Users\brichardson\Documents\command_test\my command.bat"' with argument '"arg with spa
ces"'"
C:\Users\brichardson\Documents\command_test>C:\Users\brichardson\Documents\command_test\my^ command.
bat arg^ with^ spaces
C:\Users\brichardson\Documents\command_test>echo "Called as 'C:\Users\brichardson\Documents\command_
test\my command.bat' with argument 'arg'"
"Called as 'C:\Users\brichardson\Documents\command_test\my command.bat' with argument 'arg'"
C:\Users\brichardson\Documents\command_test>C:\Users\brichardson\Documents\command_test\my^ command.
bat "arg with spaces"
C:\Users\brichardson\Documents\command_test>echo "Called as 'C:\Users\brichardson\Documents\command_
test\my command.bat' with argument '"arg with spaces"'"
"Called as 'C:\Users\brichardson\Documents\command_test\my command.bat' with argument '"arg with spa
ces"'"
C:\Users\brichardson\Documents\command_test>"C:\Users\brichardson\Documents\command_test\my command.
bat" "arg with spaces"
C:\Users\brichardson\Documents\command_test>echo "Called as '"C:\Users\brichardson\Documents\command
_test\my command.bat"' with argument '"arg with spaces"'"
"Called as '"C:\Users\brichardson\Documents\command_test\my command.bat"' with argument '"arg with s
paces"'"
任何人都可以向我解释 Windows 命令提示符何时会或不会转义空格吗?当它存在或不存在时,它实际上会在环境中存储什么?
据我所知,它只转义命令路径中的空格,并且仅当包含驱动器号时。如果您使用引号来处理空格,它会将它们包含在传递给命令的任何字符串中。
要了解的最重要的一点是,解析发生在两个不同的阶段。第一阶段是命令解释器寻找特殊字符,例如输入重定向。第二阶段是可执行文件将命令行的剩余部分解析为单独的参数。
在这种特殊情况下,您是 运行 批处理文件,因此解析的第二阶段由批处理程序处理。 (请注意,批处理器实际上并不是命令解释器的独立进程,但出于我们的目的,最好将它们视为概念上不同的。)
所以如果你从
开始
myapp.exe two^ is ^> one, "I think" > test.txt
命令解释器重定向输出并将此命令行传递给可执行文件:
myapp.exe two is > one, "I think"
如果可执行文件使用 C 运行时提供的默认解析,则成为一个数组
"myapp.exe", "two", "is", ">", "one,", "I think"
(this question 的答案更详细地说明了如何处理命令行。)
这与您的问题相关的第一个原因是因为 ^
在解析的第一阶段只是一个特殊字符。因此,它会转义 >
<
和 |
等特殊字符,但不会影响将命令行拆分为单独参数的方式。这解释了许多测试用例的行为。
这相关的第二个原因是第二阶段的解析规则完全取决于可执行文件,或者在这种情况下是批处理程序,来决定。碰巧的是,当参数包含空格时,批处理程序会选择保留引号。 (这大概是为了正确处理包含空格的文件名;大多数批处理文件参数都是文件名。)
注意: 如果您不需要引号,请使用 %~1
而不是 %1
。这记录在 for
命令的上下文中,但也适用于命令行参数。
还应注意,C 运行时库提供的默认解析不包括引号作为参数的一部分。
...我认为这涵盖了所有内容,除了...
观察
c:\path\my^ command
运行 my command
而不是 my
令我感到惊讶。我无法解释这个。如果 my command
是基于 C 的可执行文件,这是一个特别糟糕的消息,因为 "command" 将加倍,即,可执行文件会将其视为第一个参数。
我认为这是一个错误。我建议您避免这样做。
我在 Linux 环境中积累了很多经验,但现在我需要在 Windows 中做一些事情。我在弄清楚如何在 windows 命令环境中正确转义空格时遇到了一些麻烦。关于它如何解析命令的规则完全不清楚。
例如,在Linux环境中,我可以创建以下脚本:
我的command.sh
#!/bin/bash
echo "Called as '[=11=]' with argument ''"
并像这样执行它,所有可能的转义空格的方法都是等价的。
[bradworkubuntu:~/command_test] my\ command.sh arg\ with\ spaces
Called as './my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] "my command.sh" arg\ with\ spaces
Called as './my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] my\ command.sh "arg with spaces"
Called as './my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] "my command.sh" "arg with spaces"
Called as './my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] /home/brichardson/command_test/my\ command.sh arg\ with\ spaces
Called as '/home/brichardson/command_test/my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] "/home/brichardson/command_test/my command.sh" arg\ with\ spaces
Called as '/home/brichardson/command_test/my command.sh' with argument 'arg with spaces'
[bradworkubuntu:~/command_test] "/home/brichardson/command_test/my command.sh" "arg with spaces"
Called as '/home/brichardson/command_test/my command.sh' with argument 'arg with spaces'
但是当我在 Windows 上尝试类似的东西时,结果完全不一致。
我的command.bat
echo "Called as '%0' with argument '%1'"
像这样执行:
C:\Users\brichardson\Documents\command_test>my^ command.bat arg^ with^ spaces
'my' is not recognized as an internal or external command,
operable program or batch file.
C:\Users\brichardson\Documents\command_test>"my command.bat" arg^ with^ spaces
C:\Users\brichardson\Documents\command_test>echo "Called as '"my command.bat"' with argument 'arg'"
"Called as '"my command.bat"' with argument 'arg'"
C:\Users\brichardson\Documents\command_test>my^ command.bat "arg with spaces"
'my' is not recognized as an internal or external command,
operable program or batch file.
C:\Users\brichardson\Documents\command_test>"my command.bat" "arg with spaces"
C:\Users\brichardson\Documents\command_test>echo "Called as '"my command.bat"' with argument '"arg w
ith spaces"'"
"Called as '"my command.bat"' with argument '"arg with spaces"'"
C:\Users\brichardson\Documents\command_test>\Users\brichardson\Documents\command_test\my^ command.ba
t arg^ with^ spaces
'\Users\brichardson\Documents\command_test\my' is not recognized as an internal or external command,
operable program or batch file.
C:\Users\brichardson\Documents\command_test>"\Users\brichardson\Documents\command_test\my command.ba
t" arg^ with^ spaces
C:\Users\brichardson\Documents\command_test>echo "Called as '"\Users\brichardson\Documents\command_t
est\my command.bat"' with argument 'arg'"
"Called as '"\Users\brichardson\Documents\command_test\my command.bat"' with argument 'arg'"
C:\Users\brichardson\Documents\command_test>"\Users\brichardson\Documents\command_test\my command.ba
t" "arg with spaces"
C:\Users\brichardson\Documents\command_test>echo "Called as '"\Users\brichardson\Documents\command_t
est\my command.bat"' with argument '"arg with spaces"'"
"Called as '"\Users\brichardson\Documents\command_test\my command.bat"' with argument '"arg with spa
ces"'"
C:\Users\brichardson\Documents\command_test>C:\Users\brichardson\Documents\command_test\my^ command.
bat arg^ with^ spaces
C:\Users\brichardson\Documents\command_test>echo "Called as 'C:\Users\brichardson\Documents\command_
test\my command.bat' with argument 'arg'"
"Called as 'C:\Users\brichardson\Documents\command_test\my command.bat' with argument 'arg'"
C:\Users\brichardson\Documents\command_test>C:\Users\brichardson\Documents\command_test\my^ command.
bat "arg with spaces"
C:\Users\brichardson\Documents\command_test>echo "Called as 'C:\Users\brichardson\Documents\command_
test\my command.bat' with argument '"arg with spaces"'"
"Called as 'C:\Users\brichardson\Documents\command_test\my command.bat' with argument '"arg with spa
ces"'"
C:\Users\brichardson\Documents\command_test>"C:\Users\brichardson\Documents\command_test\my command.
bat" "arg with spaces"
C:\Users\brichardson\Documents\command_test>echo "Called as '"C:\Users\brichardson\Documents\command
_test\my command.bat"' with argument '"arg with spaces"'"
"Called as '"C:\Users\brichardson\Documents\command_test\my command.bat"' with argument '"arg with s
paces"'"
任何人都可以向我解释 Windows 命令提示符何时会或不会转义空格吗?当它存在或不存在时,它实际上会在环境中存储什么?
据我所知,它只转义命令路径中的空格,并且仅当包含驱动器号时。如果您使用引号来处理空格,它会将它们包含在传递给命令的任何字符串中。
要了解的最重要的一点是,解析发生在两个不同的阶段。第一阶段是命令解释器寻找特殊字符,例如输入重定向。第二阶段是可执行文件将命令行的剩余部分解析为单独的参数。
在这种特殊情况下,您是 运行 批处理文件,因此解析的第二阶段由批处理程序处理。 (请注意,批处理器实际上并不是命令解释器的独立进程,但出于我们的目的,最好将它们视为概念上不同的。)
所以如果你从
开始myapp.exe two^ is ^> one, "I think" > test.txt
命令解释器重定向输出并将此命令行传递给可执行文件:
myapp.exe two is > one, "I think"
如果可执行文件使用 C 运行时提供的默认解析,则成为一个数组
"myapp.exe", "two", "is", ">", "one,", "I think"
(this question 的答案更详细地说明了如何处理命令行。)
这与您的问题相关的第一个原因是因为 ^
在解析的第一阶段只是一个特殊字符。因此,它会转义 >
<
和 |
等特殊字符,但不会影响将命令行拆分为单独参数的方式。这解释了许多测试用例的行为。
这相关的第二个原因是第二阶段的解析规则完全取决于可执行文件,或者在这种情况下是批处理程序,来决定。碰巧的是,当参数包含空格时,批处理程序会选择保留引号。 (这大概是为了正确处理包含空格的文件名;大多数批处理文件参数都是文件名。)
注意: 如果您不需要引号,请使用 %~1
而不是 %1
。这记录在 for
命令的上下文中,但也适用于命令行参数。
还应注意,C 运行时库提供的默认解析不包括引号作为参数的一部分。
...我认为这涵盖了所有内容,除了...
观察
c:\path\my^ command
运行 my command
而不是 my
令我感到惊讶。我无法解释这个。如果 my command
是基于 C 的可执行文件,这是一个特别糟糕的消息,因为 "command" 将加倍,即,可执行文件会将其视为第一个参数。
我认为这是一个错误。我建议您避免这样做。