Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在";命令中引用空格;对于/F";在Windows上循环_Windows_For Loop_Escaping_Quotes_Spaces - Fatal编程技术网

如何在";命令中引用空格;对于/F";在Windows上循环

如何在";命令中引用空格;对于/F";在Windows上循环,windows,for-loop,escaping,quotes,spaces,Windows,For Loop,Escaping,Quotes,Spaces,对于命令,我有以下 for /F %s in ('"mas ter\gradlew.bat" -q -p mass ter') do echo %s 我不能让它正常工作。这不是实际的用例,而是一个非常简化的示例 执行 "mas ter\gradlew.bat" -q -p "mas ter" 很好 "mas ter\gradlew.bat" -q -p mass ter 表示项目目录“mass”不存在(额外的“s”仅用于区分目的) 表示未找到命令“mas” 到目前为止,这是意料之中的,但现

对于命令,我有以下

for /F %s in ('"mas ter\gradlew.bat" -q -p mass ter') do echo %s
我不能让它正常工作。这不是实际的用例,而是一个非常简化的示例

执行

"mas ter\gradlew.bat" -q -p "mas ter"
很好

"mas ter\gradlew.bat" -q -p mass ter
表示项目目录“mass”不存在(额外的“s”仅用于区分目的)

表示未找到命令“mas”

到目前为止,这是意料之中的,但现在我想让它在for循环中工作

for /F %s in ('mas ter\gradlew.bat -q -p mass ter') do echo %s
当然,他再次指出,没有找到“mas”命令

for /F %s in ('"mas ter\gradlew.bat" -q -p mass ter') do echo %s
当然,他再次表示,direcotry“mass”项目并不存在,但现在它来了

for /F %s in ('"mas ter\gradlew.bat" -q -p "mass ter"') do echo %s
再次声明没有找到命令“mas”。欧欧欧

现在我在wtf。
为什么会发生这种情况?我如何使其工作?
^
字符转义空格也不起作用。
除此之外,这也没什么帮助,因为这两条路径存储在参数中,使用起来就像

for /F %s in ('"%script_path%\gradlew.bat" -q -p "%script_path%"') do echo %s

这真是一个令人沮丧的问题,因为命令的解析很奇怪

('"mas ter\gradlew.bat" -q -p mass ter')
但在first和任何其他参数中都不能有双引号

('"mas ter\gradlew.bat" -q -p "mass ter"')
下面的一些东西可以

('master\gradlew.bat -q -p mass ter')
所以我带了一些东西来做这件事

par ams.bat

@echo off
SET COMMAND=%~1
SHIFT
%COMMAND %%*
名称中带有空格的文件,并回显每个参数。我还创建了与
params.bat

@echo off
setlocal enabledelayedexpansion
echo "You sent '%*'"
set argC=0
for %%x in (%*) do (
    Set /A argC+=1
    echo !argC! is %%x
)
echo %argC%

F:\params.sh>"par ams.bat" 1 2 "ab c"
"You sent '1 2 "ab c"'"
1 is 1
2 is 2
3 is "ab c"
3
这说明了我需要做什么

现在需要一个文件来测试设置

@echo off

for /F "tokens=* delims=" %%s in (params.bat " -q" "  -p " "abc"`) do echo %%s
这很有效

"You sent '" -q" "  -p " "abc"'"
0 is " -q"
0 is "  -p "
0 is "abc"
3
接下来是尝试
par ams.bat
。我尝试了不同的变化

for /F "tokens=* delims=" %%s in ('par ams.bat " -q" "  -p " "abc"') do echo %%s
for /F "tokens=* delims=" %%s in ('"par ams.bat" " -q" "  -p " "abc"') do echo %%s
for /F "tokens=* delims=" %%s in ('par ams.bat' " -q" "  -p " "abc"') do echo %%s
for /F "tokens=* delims= usebackq" %%s in (`'par ams.bat' " -q" "  -p " "abc"`) do echo %%s
for /F "tokens=* delims= usebackq" %%s in (`"par ams.bat" " -q" "  -p " "abc"`) do echo %%s
以上这些都不起作用。所以结论是,第一个参数没有空格,然后是任何带空格或引号的参数,没有问题。所以我提出了一个额外的批处理文件

escape.bat

@echo off
SET COMMAND=%~1
SHIFT
%COMMAND %%*
该文件不执行任何操作,只接受第一个参数作为要执行的内容,然后接受该参数的命令行参数。现在我更新了测试以使用

for /F "tokens=* delims=" %%s in ('escape.bat "par ams.bat" " -q" "  -p " "abc"') do echo %%s
然后它成功了

F:\params.sh>test
"You sent '" -q" "  -p " "abc"'"
0 is " -q"
0 is "  -p "
0 is "abc"
3
Edit-1:使用call而不是escape.bat

@echo off
SET COMMAND=%~1
SHIFT
%COMMAND %%*
谢谢你对这个“吸血鬼”的反馈。因此,更好的方法是使用
call
而不是
escape.bat
。您还可以使用
set script\u dir=%~dp0
获取脚本目录,然后在批处理文件中使用相同的目录。所以我们会改变

for /F "tokens=* delims=" %%s in ('escape.bat "par ams.bat" " -q" "  -p " "abc"') do echo %%s


执行摘要:

将命令字符串括在另一组双引号中,而不管命令字符串中是否使用引号(不要使用引号):

tl;dr详细信息:

似乎/f的
。。。('command')
variant只是将命令字符串传递到
cmd/c
(或一些等效的内部代码)以实际运行该命令

通常,cmd.exe具有复杂、随意且有缺陷的报价处理规则。
cmd/c
的特定规则包括从
cmd/?
帮助文本复制的规则:

the following logic is used to process quote (") characters:

    1.  If all of the following conditions are met, then quote characters
        on the command line are preserved:

        - no /S switch
        - exactly two quote characters
        - no special characters between the two quote characters,
          where special is one of: &<>()@^|
        - there are one or more whitespace characters between the
          two quote characters
        - the string between the two quote characters is the name
          of an executable file.

    2.  Otherwise, old behavior is to see if the first character is
        a quote character and if so, strip the leading character and
        remove the last quote character on the command line, preserving
        any text after the last quote character.
下面是没有
for
循环的批处理文件的运行:

C:\temp>"mas ter\gradlew.bat" -q -p "mass ter"
"Running 'C:\temp\mas ter\gradlew.bat'"
arg: -q
arg: -p
arg: "mass ter"
这是在带有一组双引号的
for
循环中使用的:

C:\temp>for /F "tokens=*" %s in ('""mas ter\gradlew.bat" -q -p "mass ter""') do @echo from the for loop: "%s"
from the for loop: ""Running 'C:\temp\mas ter\gradlew.bat'""
from the for loop: "arg: -q"
from the for loop: "arg: -p"
from the for loop: "arg: "mass ter""

感谢@Vampire的反馈,那么也许为什么不使用
set script_dir=%~sdp0
来获取8.3名称,然后就不需要调用了?现在删除的一个问题还建议使用8.3名称,不幸的是,它们可以被停用,即使它们被激活,也只有新创建的路径才能获得一个。对我来说,e。GC激活了它们,D停用了它们,我不是故意这么做的。因此,使用8.3名称不是很安全。否则它将是一个有效的解决方案,因为这样您就不需要在command.Old问题周围加引号,但您可以使用“setlocal enabledayedexpansion”和!而不是%。%替换发生在循环运行之前-每次语句运行时都会发生替换。@MatthewLundberg,我再也没有任何Windows机器了。如果你愿意,我建议在你的答案中添加一个额外的部分,我会继续编辑,如果你不喜欢,可以回滚。
C:\temp>"mas ter\gradlew.bat" -q -p "mass ter"
"Running 'C:\temp\mas ter\gradlew.bat'"
arg: -q
arg: -p
arg: "mass ter"
C:\temp>for /F "tokens=*" %s in ('""mas ter\gradlew.bat" -q -p "mass ter""') do @echo from the for loop: "%s"
from the for loop: ""Running 'C:\temp\mas ter\gradlew.bat'""
from the for loop: "arg: -q"
from the for loop: "arg: -p"
from the for loop: "arg: "mass ter""