在批处理文件参数中保留 "="(等号)字符

17

我编写了一个批处理文件来启动一个应用程序(该应用程序不是我的,我无法修改它)。批处理文件本身接受一些参数。应用程序接受其他参数。批处理文件使用SHIFT消耗所有选项,然后以正确的环境启动应用程序并将其余参数传递给应用程序。调用批处理文件的示例:

script.bat -opt-1 -opt-2 /opt-a /opt-b=value
在这个例子中," -opt-1 "和" -opt-2 "被 script.bat 所使用。最后,必须使用参数"/ opt-a"和"/ opt-b=value"调用原始应用程序。最后一个参数中的"="符号是应用程序所期望的,我不能更改它。当我直接从命令行调用应用程序时,它运行良好。
但是,当我从脚本中调用它时,应用程序会收到关于"/ opt-b=value"的两个参数:"/ opt-b"和"value"。如果我在调用应用程序时使用"%*",则"="符号将被保留,但是所有参数都将被传递(包括使用SHIFT跳过的参数)。
是否有办法仅传递最后一个参数并保留"="符号?

也许你可以使用DOS的转义字符:^ - Corey Ogburn
我尝试了,它不起作用。双引号 " 和单引号 ' 也不行。 - Florent Georges
也许你可以发布你的脚本,这样人们就可以复制粘贴它,看看哪里出了问题,并提出修复建议。 - indiv
3
它可以在https://github.com/fgeorges/expath-pkg-java/blob/master/bin/calabash.bat上找到。 在最后,它使用“%*”,这有助于保留“=”,但包括使用“shift”跳过的所有参数(一些参数被消耗,从第230行开始)。 - Florent Georges
4个回答

7

以这种方式调用您的script.bat脚本:

script.bat -opt-1 -opt-2 /opt-a "/opt-b=value"

并且在script.bat文件中,以以下方式调用应用程序:

rem Consume -opt-1
shift
rem Consume -opt-2
shift
rem Call the application
application %1 %~2

编辑: 回应评论

好的,让我们详细地审查这个问题。

下面是script.bat文件:

@echo off
rem Consume -opt-1
shift
rem Consume -opt-2
shift
rem Call the application
ECHO application %1 %~2

请注意ECHO命令,当第四个参数被引号包含时,正确的"调用"应用程序是使用第二个参数包括等号,如下一个屏幕输出所示:
C:\> script.bat -opt-1 -opt-2 /opt-a "/opt-b=value"
application /opt-a /opt-b=value

然而,如果应用程序是批处理文件,则会遇到与原始 script.bat 文件相同的问题。您说:“当我直接从命令行调用应用程序时,它能够正常工作。” 这并不正确。
C:\> type application.bat
@echo off
rem ** application.bat **
echo 1: %1
echo 2: %2
echo 3: %3
echo 4: %4 

C:\> application /opt-a /opt-b=value
1: /opt-a
2: /opt-b
3: value
4:

批处理文件的参数可以用逗号、分号或等号进行分隔,除了空格和制表符。因此,如果“应用程序期望在最后一个参数中使用等号”,那么没有任何理由使用批处理文件而不是应用程序来测试此方法。

你用这个方法测试了真实应用程序吗?


谢谢!不幸的是,当我尝试使用以下脚本运行上述命令时:<pre> rem ** script.bat ** rem Consume -opt-1 shift rem Consume -opt-2 shift rem Call the application call %dp0\application.bat %1 %2 </pre> <pre> rem ** application.bat ** echo 1: %1 echo 2: %2 echo 3: %3 echo 4: %4 </pre> 当使用 script.bat -opt-1 -opt-2 /opt-a "/opt-b=value" 调用时,输出结果为:<pre> 1: /opt-a 2: /opt-b 3: 4: </pre> 而不是预期的(我只想按原样传递参数):<pre> 1: /opt-a 2: /opt-b=value 3: 4: </pre> - Florent Georges
抱歉,我不确定如何添加格式良好的注释,就像您上面的那个(通过将文件正确格式化为文本块)。问题是,我尝试了您的解决方案,它传递了/opt-b而不是/opt-b=value - Florent Georges
@FlorentGeorges:我认为这里有些混淆了;请阅读我回答中的编辑... - Aacini
那么调用批处理文件和其他东西之间是有区别的。我不知道,抱歉。使用application.bat只是为了快速测试它(我想隔离问题)。真正的情况是这样的:script.bat调用application(一个“真正”的应用程序,而不是批处理脚本),并旨在供最终用户使用,作为从命令行“正确”和轻松地启动应用程序的便捷脚本。另一个项目提供other.bat,它调用script.bat以便正确启动application - Florent Georges
因此,other.bat 必须调用 script.bat,并在结尾处加上 /opt-b=value,然后将其“原样”传递给 application - Florent Georges

2
FOR /f "tokens=1*" %%x IN ("%*") DO ECHO application %%y

其中1是要跳过的参数数量。


测试中...主要的.bat文件(q20572424.bat)

@ECHO OFF
SETLOCAL
ECHO master[%*]
FOR /f "tokens=2*" %%x IN ("%*") DO CALL q20572424a.bat %%y
FOR /f "tokens=1*" %%x IN ("%*") DO CALL q20572424a.bat %%y
FOR /f "tokens=*" %%x IN ("%*") DO CALL q20572424a.bat %%x
GOTO :EOF

子公司.bat(q20572424a.bat)

@ECHO OFF
SETLOCAL
ECHO slave=[%*]
FOR /f "tokens=2*" %%x IN ("%*") DO CALL q20572424b.bat %%y
FOR /f "tokens=1*" %%x IN ("%*") DO CALL q20572424b.bat %%y
FOR /f "tokens=*" %%x IN ("%*") DO CALL q20572424b.bat %%x
GOTO :EOF

第二个子文件夹 .bat (q20572424b.bat)

@ECHO OFF
SETLOCAL
ECHO subslave=[%*]
GOTO :EOF

结果:

从运行 q20572424 -opt-1 -opt-2 /opt-a /opt-b=value

master[-opt-1 -opt-2 /opt-a /opt-b=value]
slave=[/opt-a /opt-b=value]
subslave=[]
subslave=[/opt-b=value]
subslave=[/opt-a /opt-b=value]
slave=[-opt-2 /opt-a /opt-b=value]
subslave=[/opt-b=value]
subslave=[/opt-a /opt-b=value]
subslave=[-opt-2 /opt-a /opt-b=value]
slave=[-opt-1 -opt-2 /opt-a /opt-b=value]
subslave=[/opt-a /opt-b=value]
subslave=[-opt-2 /opt-a /opt-b=value]
subslave=[-opt-1 -opt-2 /opt-a /opt-b=value]

看起来是正确的。在每种情况下,子批处理程序都直接接收参数;每次调用时删除的前导参数数量分别为2、1、0。

W7HP - 对我有效!


谢谢!这确实使用echo显示了正确的答案。但是,如果您通过实际调用应用程序来更改echo,例如call %~dp0\application.bat,其中application.bat显示其参数,则结果为:“1:/opt-a,2:/opt-b,3:value”。因此,最后一个参数实际上已被拆分成两个...预期结果是:1:/opt-a,2:/opt-b=value - Florent Georges

0

0

这会在任何“带空格引号”的参数上出错,虽然是个巧妙的技巧,但它只适用于基本参数。 - ericpeters

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接