先来说说变量延迟扩展吧。当然,放狗一搜,就能看到满天飞的关于变量延迟扩展的文章,所以,我这里就简单介绍一下。先来看一段批处理:
1 2 3 4 5 6 | set str=test if %str%==test ( set str=another test echo %str% ) |
上面的代码段极其简单,给str赋值,判断其值是否为test,如果是,重新赋值为another test,再显示str的值。
作为正常人的思维,这里显示的肯定是another test了,但其实不是,其显示的仍然是test,这是为什么?因为:windows在解释执行此代码段时,在遇到if语句后的括号后,只把它当一条语句处理而不是两条语句,所以,在第二条语句中的%str%会被替换成它目前的值test,上面的代码相当于下面的代码的效果:
1 2 3 4 5 6 | set str=test if %str%==test ( set str=another test echo test ::注意这里 ) |
所以,输出自然是test了。
这样编程的灵活性就大大降低了,于是,M$就想了一个workground的方法,那就是变量延迟,很简单,看如下代码:
1 2 3 4 5 6 7 8 9 10 | @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%引用是不起作用的。
好了,变量延迟扩展解释完了,至少这就是我知道的变量延迟扩展。
今天变量延迟扩展和感叹号让我蛋疼了半天,所以现在也要来扯扯它们的蛋。
试试以下代码段:
1 2 3 4 5 6 7 | @echo off setlocal enabledelayedexpansion set str=test!!! echo %str% |
开启变量延迟,给str赋值,输出str,于是,输出自然是test!!!了。但其实,windows告诉我们,又错了,输出是test,感叹号被windows吃了。
当然如果注释掉开启变量延迟那一行,这几行是可以正常工作的,所以说是开启变量延迟影响了我们正常的工作,但我至今还没搞清楚为什么会这样,这只有M$知道。
于是,关闭变量延迟吧,可是程序又需要使用变量延迟来实现一些逻辑,怎么办?两个办法:
-
暂时关闭变量延迟:
123456789101112131415@echo off
setlocal enabledelayedexpansion
::
do
something here
setlocal disabledelayedexpansion ::关闭变量延迟
set
str=test!!!
echo %str%
setlocal enabledelayedexpansion
::
continue
...
在需要处理感叹号的地方,暂时关闭变量延迟,处理完后再打开。这时能正常输出感叹号。
-
在开启变量延迟之前set:
1234567@echo off
set
str=test!!!
setlocal enabledelayedexpansion
echo !str! ::注意这里
在开启变量延迟之前设置好变量,但是要注意,在使用变量的时候,需要使用感叹号引用。这时感叹号也可以正常输出。
最后贴一段为什么让我蛋疼的代码(变量延迟自然是打开的):
1 2 3 4 5 6 | 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的值。。。
原文链接:
https://kelvinh.github.io/blog/2012/02/16/batch-delayed-expansion/
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~