批处理之 正确使用for语句 以及!errorlevel!、%errorlevel% 与 DelayedExpansion用法详解

13 篇文章 0 订阅
    昨天在使用批处理中的 for 语句的时候,最初我采用下面这种写法:
@echo off
set ip=192.168.1
for /l %%i in (1,1,5) do (
    set ip=%ip%.%%i    :: 遍历 IP 池
    echo ip=%ip%  i=%%i
)

图1
    运行结果如上图,显示变量 ip 的值始终为 192.168.1,并没有按预期递增输出 IP。

    经过查阅资料,我找到了原因:
    1、 批处理是解释型语言,脚本不会被编译。在运行时,脚本中所引用的 变量会被简单替换成对应的文本(在批处理中称为 变量扩展,Expansion),这一点可以用 C语言中的宏来理解。
    2、批处理中对于变量的赋值(将变量进行扩展) 默认发生在第一次读取到一条完整的命令之后,注意, 命令仅仅只是被读取还没有被执行

    明白了这 2 点,上面脚本运行的错误也就解释得通了。
    对于 for 语句而言,一条完整命令的形式是 for /arg %%var in (SET) do (COMMAND) 这样的, 包括了 do 之后括号里的所有命令,所以他们只会被读取而不会被执行,自然变量 ip 也就不会被赋值了。在上文脚本中,命令 for /l %%i in (1,1,5) do (set ip=%ip%.%%i ...) 第一次被系统完整读取到时,变量 ip 的值为 192.168.1,所以变量 ip 的打印结果一直是 192.168.1
    幸好,微软的工程师在开发解释器时已经发现了这一点,并为我们提供了 setlocal 命令用于 改变解释器的规则

    将上文脚本更改成下面的写法:
@echo off
setlocal EnableDelayedExpansion
set ip=192.168.1
for /l %%i in (1,1,5) do (
    set ip=%ip%.%%i
    echo ip=!ip!  i=%%i
)
:: 写成 enabledelayedexpansion 也是可以的,不区分大小写
:: 必须使用英文感叹号 ! 而不是百分号来引用需要延时扩展的变量,!ip!

图2
    这次的运行结果从上图可以看到,输出和计划一致。

    使用 setlocal EnableDelayedExpansion 命令后,可以让解释器在每次循环的执行过程中都对变量 ip 进行一次赋值。这种 循环体中为变量多次赋值的操作在批处理中 叫做 对变量进行延时扩展(Delayed Expansion)
    再来看 2 个例子,搞清楚使用感叹号 ! 和百分号 % 的区别:
【例 1】
@echo off
setlocal enabledelayedexpansion
echo 开始搜索文件,请等待程序提示“搜索完成”再退出 ...
echo.
for /r /d %%i in (.) do (
    dir %%i *.xls* 2>nul | find /i "xls"
    if %errorlevel% equ 0 (    :: 此处使用百分号 %
        echo  文件位置 %%i
    )
)
echo.
echo 搜索完成!回车可退出。
pause >nul

图3

【例 2】
@echo off
setlocal enabledelayedexpansion
echo 开始搜索文件,请等待程序提示“搜索完成”再退出 ...
echo.
for /r /d %%i in (.) do (
    dir %%i *.xls* 2>nul | find /i "xls"
    if !errorlevel! equ 0 (    :: 此处使用感叹号 !
        echo  文件位置 %%i
    )
)
echo.
echo 搜索完成!回车可退出。
pause >nul

图4
    执行结果的对比很明显。 使用百分号 % 时,if 条件判断语句中的 errorlevel 值表示第一次读取完整 for 命令时的值,也就是执行完 echo. 命令后的 errorlevel(有点绕,不着急,好好想想)。命令 echo. 执行成功,所以 errorlevel 一直都是 0,这导致输出结果中打印了很多无用的信息。 使用感叹号 ! 时,if 条件判断语句中的 errorlevel 值是 for 循环中每次执行完 find 命令后的 errorlevel 值,这才是我们计划中要用的。
    有关 延时扩展变量 的用法,不知道现在你懂了没有?
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
第一章 批处理基础 第一节 常用批处理内部命令简介 1、REM 和 :: 2、ECHO 和 @ 3、PAUSE 暂停 4、ERRORLEVEL 5、TITLE 设置cmd窗口的标题 6、COLOR 设置cmd窗口前景和背景颜色 7、mode 配置系统设备 8、GOTO 和 : 9、FIND 在文件中搜索字符串 10、START 调用外部程序并任其在新窗口自行运行 11、assoc 和 ftype 12、pushd 和 popd 13、CALL 调用批处理程序或命令并等待其执行完毕 14、shift 15、IF 16、setlocal 与 变量延迟 17、ATTRIB 显示或更改文件属性 18、findstr 在文件中搜索字符串(find增强版) 19、date /t 和 time /t 第二节 常用特殊符号 1、@ 命令行回显屏蔽符 2、% 批处理变量引导符 3、> 输出重定向符 4、>> 输出重定向符 5、<、>&、<& 重定向符 6、| 命令管道符 7、^ 转义字符 8、& 组合命令(顺序执行) 9、&& 组合命令(前面指令成功,才执行后面指令) 10、|| 组合命令(前面指令失败,才执行后面指令) 11、"" 字符串界定符 12、, 逗号 13、; 分号 14、() 括号 15、! 感叹号 16、批处理中可能会见到的其它特殊标记符: (略) CR(0D) 命令行结束符 Escape(1B) ANSI转义字符引导符 Space(20) 常用的参数界定符 Tab(09) ; = 不常用的参数界定符 + COPY命令文件连接符 * ? 文件通配符 / 参数开关引导符 : 批处理标签引导符 第二章 FOR命令详解 一、基本格式 二、参数 /d 主要搜索匹配目录 三、参数 /R 搜索指定目录树中的匹配文件 四、参数 /L 按数字序列(start,step,end)循环 五、参数 /F 处理命令输出、字符串及文件内容 第三章 FOR命令中的变量 一、 ~I - 删除任何引号("),扩展 %I 二、 %~fI - 将 %I 扩展到一个完全合格的路径名 三、 %~dI - 仅将 %I 扩展到一个驱动器号 四、 %~pI - 仅将 %I 扩展到一个路径 五、 %~nI - 仅将 %I 扩展到一个文件名 六、 %~xI - 仅将 %I 扩展到一个文件扩展名 七、 %~sI - 扩展的路径只含有短名 八、 %~aI - 将 %I 扩展到文件的文件属性 九、 %~tI - 将 %I 扩展到文件的日期/时间 十、 %~zI - 将 %I 扩展到文件的大小 十一、 %~$PATH:I 第四章 批处理中的变量 一、系统变量 二、自定义变量 第五章 set命令详解 一、用set命令设置自定义变量 二、用set命令进行简单计算 三、用set命令进行字符串处理 1、字符串替换 2、字符串截取 第六章 if命令讲解 第一种用法:IF [NOT] ERRORLEVEL number command 第二种用法:IF [NOT] string1==string2 command 第三种用法:IF [NOT] EXIST filename command 第四种用法:IF增强的用法 第七章 DOS编程高级技巧 一、交互界面设计 二、if…else…条件语句 三、循环语句 四、子程序 五、用ftp命令实现自动下载 六、用7-ZIP实现命令行压缩和解压功能 七、调用VBScript程序 八、将批处理转化为可执行文件 九、时间延迟 1、利用ping命令延时 2、利用for命令延时 3、利用vbs延迟函数,精确度毫秒,误差1000毫秒内 4、仅用批处理命令实现任意时间延迟,精确度10毫秒,误差50毫秒内 十、模拟进度条 十一、特殊字符的输入及应用 十二、随机数(%random%)的应用技巧 十三、变量嵌套 与 命令嵌套 十四、文件内容筛选(type和findstr命令结合使用

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值