先来说说变量延迟扩展吧。当然,放狗一搜,就能看到满天飞的关于变量延迟扩展的文章,所以,我这里就简单介绍一下。先来看一段批处理:



set  str = test  if  %str% == test  (   set  str = another test  echo  %str%  )





上面的代码段极其简单,给str赋值,判断其值是否为test,如果是,重新赋值为another test,再显示str的值。

作为正常人的思维,这里显示的肯定是another test了,但其实不是,其显示的仍然是test,这是为什么?因为:windows在解释执行此代码段时,在遇到if语句后的括号后,只把它当一条语句处理而不是两条语句,所以,在第二条语句中的%str%会被替换成它目前的值test,上面的代码相当于下面的代码的效果:



set  str = test  if  %str% == test  (   set  str = another test  echo  test  :: 注意这里   )



所以,输出自然是test了。

这样编程的灵活性就大大降低了,于是,M$就想了一个workground的方法,那就是变量延迟,很简单,看如下代码:



@echo   off   setlocal  enabledelayedexpansion  :: 注意这里     set  str = test  if  %str% == test  (   set  str = another test  echo  !str!  :: 注意这里     echo  %str%  :: 区别   )




现在会输出什么呢?试一下就知道,第一行输出another test,第二行输出test。

现在解释一下,setlocal enabledelayedexpansion用于开启变量延迟,这是告诉解释器,在遇到复合语句的时候,不要将其作为一条语句同时处理,而仍然一条一条地去解释。但是这时必须用!str!来引用变量,如果仍然用%str%引用是不起作用的。

好了,变量延迟扩展解释完了,至少这就是我知道的变量延迟扩展。

====== 我是自豪的分割线,如果你只想知道变量延迟扩展是怎么回事,看到这里就OK了 =====

今天变量延迟扩展和感叹号让我蛋疼了半天,所以现在也要来扯扯它们的蛋。

试试以下代码段:



@echo   off   setlocal  enabledelayedexpansion  set  str = test!!!  echo  %str%




开启变量延迟,给str赋值,输出str,于是,输出自然是test!!!了。但其实,windows告诉我们,又错了,输出是test,感叹号被windows吃了。

当然如果注释掉开启变量延迟那一行,这几行是可以正常工作的,所以说是开启变量延迟影响了我们正常的工作,但我至今还没搞清楚为什么会这样,这只有M$知道。

于是,关闭变量延迟吧,可是程序又需要使用变量延迟来实现一些逻辑,怎么办?两个办法:

1.暂时关闭变量延迟:



@echo   off   setlocal  enabledelayedexpansion  ::  do something here   setlocal  disabledelayedexpansion  :: 关闭变量延迟   set  str = test!!!  echo  %str%  setlocal  enabledelayedexpansion  ::  continue...




在需要处理感叹号的地方,暂时关闭变量延迟,处理完后再打开。这时能正常输出感叹号。

2.在开启变量延迟之前set:



@echo   off   set  str = test!!!  setlocal  enabledelayedexpansion  echo  !str!  :: 注意这里





在开启变量延迟之前设置好变量,但是要注意,在使用变量的时候,需要使用感叹号引用。这时感叹号也可以正常输出。



最后贴一段让我蛋疼并且引申出上面研究过程的代码(/变量延迟自然是打开的):



set  server = %~ 1   set  username = %~ 2   set  password = %~ 3   echo  % date % ,  % time % [INFO] Report server address: [%server%] ,  username: [%username%] ,  password: [*******] rs . exe -i  " PublishReports.rss "  -s  " %server% "  -u  " %username% "  -p  " %password% "  -l  600



为了不回显password,我输出了一大串*。在我机器上测试时,我的password字符都很常规,所以通过。但是,QA的password里面有感叹号。。。

关键的是,这里调用的是M$的Report Server的rs.exe来上传模板,它抛出一个Could not connect的exception,于是,我自然地想到是report server的service出了问题,但查了好久也没发现report server有什么问题。。。谁TMD会想到是别人的password里有感叹号,谁TMD又会想到是跟所谓延迟变量的冲突导致的,更有谁会想到,我自己自作聪明地为了不显示password而显示出了一大串hard code的星号导致看不到password的值。。。

这么多巧合在一起,谁能不蛋疼。。。



批处理 变量延迟 如何输出感叹号

在变量延迟打开的情况下如何输出感叹号!

代码:

@echo off
setlocal enabledelayedexpansion
echo ^^! 
pause

可以理解为第一次预处理时,!只是一个普通字符,,^^会脱去一个,第一个^转义第二个^。有第二次预处理是因为开启了延迟,会把第一次预处理留下的^当作转义字符,用来转义!。简单来说就是,第一次预处理,!只是普通字符,第二次预处理,!变成了特殊字符。
如下:
未开启延迟: 预处理1
开启延迟  : 预处理1、预处理2。
“预处理1”----在每个开启延迟的,或未开启延迟的批处理中,都会进行,在两个模式中,“预处理1”的运行机制是完全一样的。
只需记住,!只有在开启了延迟之后,才算特殊字符,第一次预处理时,!仅是一个普通字符,有第二次预处理,是因为开启了延迟。