J15*_*98J 5 batch-file command-prompt piping
我正在编写自己的简单系统,允许我在 APK 上传到 GPlay 之前自动对其进行签名。我有一个可以进行签名的批处理文件;和一个“包装器”批处理文件,其内容将由 Jenkins 构建后在命令行上运行。
签名APKS.bat:
@echo off
set /p job= "Enter job name: "
set /p alias= "Enter key alias: "
set /p mobile= "Sign mobile? (y/n): "
set /p wear= "Sign wear? (y/n): "
echo.
echo "%job%"
echo "%alias%"
echo "%mobile%"
echo "%wear%"
[the rest of the code is sensitive so is emitted, but these variables are used later]
Run Code Online (Sandbox Code Playgroud)
包装代码:
@echo off
(echo test
echo test
echo y
echo y)| call sign_apks.bat
Run Code Online (Sandbox Code Playgroud)
本文向我展示了如何将值通过管道传输到程序中。引用答案:
Multiple lines can be entered like so:
(echo y
echo n) | executable.exe
...which will pass first 'y' then 'n'.
Run Code Online (Sandbox Code Playgroud)
然而,这不起作用。这是运行包装器代码时得到的输出:
Enter job name: Enter key alias: Sign mobile? (y/n): Sign wear? (y/n):
"test "
""
""
""
Run Code Online (Sandbox Code Playgroud)
帮助?
SET /P 与管道输入的交互方式有一些非常奇怪的地方,我不完全理解。
但我确实有一些解决方案:-)
最简单的解决方案是将响应写入临时文件,然后使用该临时文件作为重定向输入。
@echo off
(
echo test
echo test
echo y
echo y
)>responses.temp
call sign_apks.bat <responses.temp
delete responses.temp
Run Code Online (Sandbox Code Playgroud)
这就是我解决你的问题的方法。但有些人不喜欢使用临时文件(为什么我不知道)。所以我决定尝试使用没有临时文件的管道来解决它。
我发现你的代码有一个奇怪的变体,几乎可以解决问题 - 但它在每个值的末尾附加了一个额外的不需要的空格。
@echo off
(
call echo test1
call echo test2
call echo y1
call echo y2
) | sign_apks.bat
Run Code Online (Sandbox Code Playgroud)
- 输出 -
Enter job name: Enter key alias: Sign mobile? (y/n): Sign wear? (y/n):
"test1 "
"test2 "
"y1 "
"y2 "
Run Code Online (Sandbox Code Playgroud)
我无法解释为什么 CALL 使每个 SET /P 语句都能正常工作。但我可以解释为什么每个值都附加空格。这与为什么当您使用带有管道的批处理脚本时不需要 CALL 有关。
管道的每一端都在全新的 cmd.exe 会话中执行。例如,管道的右侧变为如下命令:
C:\Windows\system32\cmd.exe /S /D /c" sign_apks.bat"
Run Code Online (Sandbox Code Playgroud)
这就是为什么不需要 CALL 的原因 - 控制权将在新的 cmd.exe 会话终止后返回。
不需要的空格是管道处理带括号的块的方式的产物。解析器必须捕获整个管道代码块并将其转换为可以合并到 CMD.EXE /C 参数中的单行。CMD.EXE 解析器通过在每个命令之间放置 & 来完成此操作。不幸的是,解析器还插入了一些额外的空格。所以管道的左侧就变成了这样:
C:\Windows\system32\cmd.exe /S /D /c" ( call echo test & call echo test & call echo y & call echo y )"
Run Code Online (Sandbox Code Playgroud)
现在您可以轻松查看不需要的尾随空格来自何处。请参阅为什么在管道代码块内延迟扩展会失败?有关如何实施管道的更多信息。
我终于想出了另一种解决方案。我创建了一个名为 WriteArgs.bat 的辅助批处理脚本,它只是 ECHO 传递给它的每个参数。
写入参数.bat
@echo off
:loop
if .%1 equ . exit /b
echo %1
shift /1
goto loop
Run Code Online (Sandbox Code Playgroud)
通过这个简单的批处理脚本,您现在可以使用以下方法解决您的问题:
WriteArgs.bat test test y y | sign_apks.bat
Run Code Online (Sandbox Code Playgroud)
再次,我不明白为什么 SET /P 在这里可以正常工作,但不能与您的原始命令一起使用。但这确实解决了问题:-)
更新-嗯,它解决了我机器上的问题。但这似乎是一个时间问题,而且我不相信任何给定的管道解决方案总是有效。我认为唯一可靠的解决方案是使用临时文件和重定向的解决方案。
您知道,最简单的解决方案是将job、alias、mobile和wear作为脚本参数提供,而不是尝试将它们通过管道传输到标准输入。set /p如果没有定义,如果您希望不带参数地交互运行,您仍然可以。
@echo off
setlocal
set "job=%~1"
set "alias=%~2"
set "mobile=%~3"
set "wear=%~4"
if not defined job set /p "job=Enter job name: "
if not defined alias set /p "alias=Enter key alias: "
if not defined mobile set /p "mobile=Sign mobile? (y/n): "
if not defined wear set /p "wear=Sign wear? (y/n): "
echo.
echo "%job%"
echo "%alias%"
echo "%mobile%"
echo "%wear%"
Run Code Online (Sandbox Code Playgroud)
然后当你call sign_apks.bat,就这样称呼它:
call sign_apks.bat test test y y
Run Code Online (Sandbox Code Playgroud)