我目前正在试验管道。所以我创建了一个简单的批处理文件(dos / windows),如下所示:
@echo off
echo [+] starting batch file
:start
set /p msg="[+] enter msg: "
echo [+] Your message: %msg%
IF "%msg%"=="x" (
echo [x] end loop
goto exit
) ELSE (
goto start
)
:exit
echo [+] bye
只要我从命令行调用它就可以正常工作:
> showAll.bat
S:\80_personalFolder\81_lab\python\ghoul>showAll.bat
[+] starting batch file
[+] enter msg: hello
[+] Your message: hello
[+] enter msg: x
[+] Your message: x
[x] end loop
[+] bye
S:\80_personalFolder\81_lab\python\ghoul>
但是当我尝试将输入传递给它时,它将以无限循环运行:
> echo hello | showAll.bat
将导致:
[...]
[+] enter msg: [+] Your message: hello
[+] enter msg: [+] Your message: hello
[+] enter msg: [+] Your message: hello
[+] enter msg: [+] Your message: hello
[+] enter msg: [+] Your message: hello
[...]
我不明白这种行为。有人可以解释我监督的内容或我错过的内容!我该如何解决这个问题,所以它不会无限期地运行,但会在循环中停止下一个提示,所以我可以手动退出?
UPDATE!首先感谢我收到的非常好的答案。它帮助我更好地理解发生了什么。所以我修改了代码以在再次调用read之前重置输入var。 我想要实现的目标如下: 1)管道回声你好'批处理脚本 2)一旦脚本从管道输入运行hello并重新进入循环... 3)...我希望能够手动输入其他内容。相反,它仍将使用脚本将变量设置为的默认值进行无限循环。如何停止管道并切换回默认的标准输入?我想这就是我真正面临的问题。我甚至不确定这可以做到。
谢谢,最好
答案 0 :(得分:6)
set /p var=
命令用于检索要存储到指示变量中的输入数据。行为是
set /p
失败(没有错误),变量未更改。第二种情况是您所看到的行为的来源。
echo
命令)在第一次迭代中读取您的代码(仅检查变量内容)没有看到两种情况之间的差异,因为变量仍保留上一次迭代的数据。
如果没有读取任何数据是循环退出的有效案例,您可以执行类似
的操作:start
set "msg="
set /p msg="[+] enter msg: "
if not defined msg goto :exit
如果没有读取数据,则在每次读取和离开之前重置变量。
这也可以用更简单的方式写成
:start
set /p msg="[+] enter msg: " || goto :exit
如果||
失败,则使用条件运算符set /p
(如果前一个命令失败,则执行next命令)离开循环。
已修改以适应评论:
所需的行为是从命令中存在的管道读取数据,但是当读取数据时,set /p
应该从用户检索数据。首先,我们需要看看管道是如何工作的。
当cmd
处理管道操作符时,会创建两个新的单独进程来处理管道的左侧和右侧。
目前,我们有三个cmd
个实例(OP问题中的情况):
cmd1
:附加到运行键入命令的控制台cmd2
:在管道左侧运行命令cmd3
:在管道右侧运行批处理文件与每个实例关联的输入/输出流(stdin
是输入流,stdout
是输出流):
cmd1
:stdin
是当前控制台stdin
,stdout
是当前控制台stdout
cmd2
:从stdin
继承控制台cmd1
,stdout
附加到stdin
cmd3
流
cmd3
:stdin
已附加到stdout
的{{1}}流,cmd2
继承自stdout
在此方案中,处理批处理文件的cmd1
无法访问cmd3
或stdin
中处于活动状态的控制台cmd1
。
所以,在这一点上,我没有找到实现指示行为的方法。
答案 1 :(得分:2)
对于您的样品,当您只接受管道中的一条线时,它很容易修复。
我只添加了'设置" msg = x"'每次重置默认值为' x',
因为set /p
在没有新输入的情况下不会更改变量
并且set /p
不会在管道上下文中等待(只是非常正确)
@echo off
echo [+] starting batch file
:start
set "msg=x"
set /p msg="[+] enter msg: "
echo [+] Your message: %msg%
IF "%msg%"=="x" (
echo [x] end loop
goto exit
) ELSE (
goto start
)
:exit
echo [+] bye