问题描述
我正在尝试使用以下代码来测试管道变量是否存在,这是我想要执行的包含脚本块内其他代码的真实代码的简化,但这演示了问题:
( if defined some_variable echo ok ) | more
echo was unexpected at this time
它给了我消息“此时回声是意外的。”在“if”语句后引用带括号并不能解决问题,它只是抱怨括号
( if defined some_variable ( echo ok ) ) | more
( was unexpected at this time.
“if”语句的两种变体都可以在不在管道中的代码块中使用。
if defined some_variable echo ok
ok
if defined some_variable ( echo ok )
ok
此外,我可以执行代码块但输出到文件,这可以捕获脚本块的输出,特别是即使脚本块中有多行代码:
( if ok defined some_variable echo ok ) > some_text_file.txt
这种“if”风格在脚本块到管道结构中起作用:
( if 1==1 echo ok ) | more
ok
( if NOT 1==2 echo ok ) | more
ok
但我不明白为什么使用 'defined' 关键字的存在性测试完全破坏了这种管道结构。
我的最终目标是让以下类型的代码在批处理脚本中工作(它比下面的示例有更多的事情要做),但问题归结为开头提到的简化炸弹。下面的代码将作为批处理脚本将输出回显到命令提示符和日志文件,但脚本块中的变量检查会破坏它。
(
echo some_stuff_like_a_program_header
#test existence of a variable and if not defined earlier in script then echo some stuff
if NOT defined some_variable then_alert_user_with_error_msg
if some_variable==some_value (do_some_stuff) else (do_other_stuff)
) | powershell.exe -command '& { $input | tee-object -file out.log }'
解决方法
这是解析器的一个bug,if语句会被压缩为 if definedsome_variable echo ok
。
您会看到 defined
和 some_variable
可以通过后期变量展开来解决。
set "myLine=if defined path echo ok"
echo pipe | ( %%myLine%%)
或者使用转义空格(来自@enjoying SO:Why does the error message appear when IF
comparison is in the piped block command?)
echo pipe | ( if defined ^ path echo ok )
要查看内部发生的情况,您可以尝试此调试构造
@echo off
setlocal
(set \n=^
%=empty=%
)
set "debug=echo ### %%cmdcmdline%% ^) %%\n%%"
echo dummy | (
%debug%
if defined some_variable echo ok
)