最近使用批处理程序处理文件的时候,发现这 bat
中的变量形式真是“变化多端”,有时候加1个百分号%,有时候加2个百分号%%,还有的时候加感叹号!,真是让初学者一头雾水,于是查询资料做了一些小测试,终于大致弄清楚了这些变量的含义,接下来一一列举出来。
下面通过一些具体的例子来看下标题中提到的这些变量什么时候使用,使用的时候有哪些注意事项。
这个是批处理程序中的固定用法,类似于C++程序main
函数中argv变量数组,类比可以知道,argv[0]表示exe程序的文件名,argv[1]表示启动程序的第1个参数,后面依次类推。而在批处理程序中%0表示这个批处理程序的文件名,%1表示调用这个批处理时传入的第1个参数,%2表示调用这个批处理时传入的第2个参数,最大可以到%9,具体用法可以参考之前的总结《.bat批处理(二):%0 %1——给批处理脚本传递参数》,简单测试如下:
@echo off echo param0=%0echo param0=%1echo param0=%2
将上述代码保存在文件testparams.bat中,从cmd命令行运行批处理文件,只传入一个参数,运行结果如下:
C:\Users\Administrator\Downloads>testparams.bat “hello world”
param0=testparams.bat
param1=“hello world”
param2=
在题目所列的这些变量中,这一个比较特殊,因为它不是批处理文件中的变量,只能用于cmd命令行下的for循环中,在命令行中for循环的语法是for %variable in (set) do command [command-parameters]
,其中的variable只能是单字母或者非特殊含义的字符,同样的for循环语句如果写在批处理文件中variable之前就要加两个%%了,先来看看%i的用法,直接在命令行中遍历集合打印输出:
C:\Users\Administrator\Downloads>for %i in (1,3,5,8) do echo %i
C:\Users\Administrator\Downloads>echo 1
1
C:\Users\Administrator\Downloads>echo 3
3
C:\Users\Administrator\Downloads>echo 5
5
C:\Users\Administrator\Downloads>echo 8
8
如果将其中的%i改成%%i,就会报语法错误,测试结果如下:
C:\Users\Administrator\Downloads>for %%i in (1,3,5,8) do echo %%i
此时不应有 %%i。
这种类型也是for循环中特有的,与%i相对,属于批处理程序的用法,换句话说就是在for循环中遍历的索引变量,如果在命令行中定义需要一个%,如果相同的语句定义在批处理文件中需要2个%%,语法为for %%variable in (set) do command [command-parameters]
,variable同样只能是单个字母或者普通字符,至于为什么同样含义的变量在批处理中要多加一个%,至今也没有找到官方的说法,查找MSDN也没有发现说明,不过就我个人理解可能就像我们在命令行中打印一个%,可以正常打印输出,如果通过printf()
想输出%就需要2个%的原理一样吧,测试如下:
for %%i in (1,3,5,8) do echo %%i
运行结果:
C:\Users\Administrator\Downloads>testfor.bat
C:\Users\Administrator\Downloads>for %i in (1 3 5 8) do echo %i
C:\Users\Administrator\Downloads>echo 1
1
C:\Users\Administrator\Downloads>echo 3
3
C:\Users\Administrator\Downloads>echo 5
5
C:\Users\Administrator\Downloads>echo 8
8
观察运行结果发现,运行批处理文件的时候,实际上去掉了%%i变量的1个%,将文件中代码改为1个%试下:
for %i in (1,3,5,8) do echo %i
运行结果:
C:\Users\Administrator\Downloads>testfor.bat
此时不应有 i。
这个变量看起来挺正常的,也没有那么多奇奇怪怪的字符,和Lua、Python等语言中的变量长得挺像,实际上变量的这种形式很“短暂”,一般只能出现在给变量赋值的时候,也就是set语句之后,作为左值接受赋值时,或者在等号右测可评估的表达式中,举个例子,编写下面代码保存在normalVar.bat中:
@echo off set var1=1set /a var2=var1+1 echo var1echo var2
运行之后的结果为:
C:\Users\Administrator\Downloads>normalVar.bat
var1
var2
看完结果之后觉得很神奇是不是,为什么和我学的其他语言不一样呢,我使用set分别为var1和var2赋了值,但是输出的时候居然不是数字而是变量名,其实这就引出了之后%var%这种用法,接着往下看。
在批处理中除了上面所说的在set语句后面的两种情况,再要想引用变量就需要在变量两端各加一个百分号%,明确的告诉引用者这是一个变量,使用时需要评估一下值,而不要当成字符串,上一个例子中echo后面想要输出的变量没有加%,那就被当成一个字符串处理,原样输出了,修改上个例子如下:
@echo off set var1=1set /a var2=var1+1 set var3=%var2% echo %var1%echo %var2%echo %var3%
运行之后运行结果入下:
C:\Users\Administrator\Downloads>normalVar.bat
1
2
2
看了这次的结果感觉正常多了,有一点需要注意,set var3=%var2%
这一句中var2变量中的%不能省略,因为它既不属于左值也不属于被评估值的表达式,如果不加%,赋值后var3的值会变成“var2”这个字符串。
这是最后一种常见的变量形式,同时也是一种不太好理解的形式,需要记住一点,这种变量与延迟环境变量扩展有关,如果没开启延迟环境变量扩展,那么!var!就是一个普通的包含5个字母的字符串,如果开启了延迟环境变量扩展,那么它就是变量var的实际值,可能说到这有的人会产生疑惑,引用变量var的值不是使用%var%吗?那么在开启延迟环境变量扩展的情况下,%var%和!var!有什么区别呢?下面举个例子测试下,编写如下代码保存在extVar.bat文件中:
@echo off set var1=110set var1=120&echo %var1%
运行之后的结果为:
C:\Users\Administrator\Downloads>extVar.bat
110
看到结果的时候是不是再次怀疑了世界,在打印变量var1之前明明重新赋值了120,为什么打印出来还是110呢?其实这是批处理脚本执行机制导致的,它会按行执行,在执行之前会先预处理,当执行set var1=110
之后,变量var1变成了110,在执行set var1=120&echo %var1%
之前先预处理,将变量%var1%替换成了110,然后语句变成了set var1=120&echo 110
,所以就得到了我们上面测试的结果。
想要解决这个问题就需要开启延迟环境变量扩展,语句为setlocal enabledelayedexpansion
,然后将引用变量的形式由%var1%改为!var1!即可,所以可以修改代码如下:
@echo off setlocal enabledelayedexpansionset var1=110set var1=120&echo !var1!
运行之后的结果为:
C:\Users\Administrator\Downloads>extVar.bat
120
这回输出的结果符合预期了,开启了延迟环境变量扩展之后,!var!形式的变量在用之前才会评估确切的值,这是一个知识点,也是一个易错点,特别是在for循环中要格外注意,因为for循环语句的循环体括号中,所有的操作被看成是同一行,所以经常会用到延迟环境变量扩展。
for %i in (set) do (...)
,循环变量格式为%ifor %%i in (set) do (...)
,循环变量格式为%%isetlocal enabledelayedexpansion
,同时使用!var!形式的变量(77条消息) .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别_AlbertS Home of Technology-CSDN博客_bat 变量 .bat批处理(八):各种形式的变量%0、%i、%%i、var、%var%、!var!的含义和区别_AlbertS Home of Technology-CSDN博客_bat 变量")
原网址: 访问
创建于: 2022-11-28 09:40:35
目录: default
标签: 无
未标明原创文章均为采集,版权归作者所有,转载无需和我联系,请注明原出处,南摩阿彌陀佛,知识,不只知道,要得到
java windows火焰图_mob64ca12ec8020的技术博客_51CTO博客 - 在windows下不可行,不知道作者是怎样搞的 监听SpringBoot 服务启动成功事件并打印信息_监听springboot启动完毕-CSDN博客 SpringBoot中就绪探针和存活探针_management.endpoint.health.probes.enabled-CSDN博客 u2u转换板 - 嘉立创EDA开源硬件平台 Spring Boot 项目的轻量级 HTTP 客户端 retrofit 框架,快来试试它!_Java精选-CSDN博客 手把手教你打造一套最牛的知识笔记管理系统! - 知乎 - 想法有重合-理论可参考 安宇雨 闲鱼 机械键盘 客制化 开贴记录 文本 linux 使用find命令查找包含某字符串的文件_beijihukk的博客-CSDN博客_find 查找字符串 ---- mac 也适用 安宇雨 打字音 记录集合 B站 bilibili 自行搭建 开坑 真正的客制化 安宇雨 黑苹果开坑 查找工具包maven pom 引用地 工具网站 Dantelis 介绍的玩轴入坑攻略 --- 关于轴的一些说法 --- 非官方 ---- 心得而已 --- 长期开坑更新 [本人问题][新开坑位]关于自动化测试的工具与平台应用 机械键盘 开团 网站记录 -- 能做一个收集的程序就好了 不过现在没时间 -- 信息大多是在群里发的 - 你要让垃圾佬 都去一个地方看难度也是很大的 精神支柱 [超级前台]sprinbboot maven superdesk-app 记录 [信息有用] [环境准备] [基本完成] [sebp/elk] 给已创建的Docker容器增加新的端口映射 - qq_30599553的博客 - CSDN博客 [正在研究] Elasticsearch, Logstash, Kibana (ELK) Docker image documentation elasticsearch centos 安装记录 及 启动手记 正式服务器 39 elasticsearch 问题合集 不断更新 6.1.1 | 6.5.1 两个版本 博客程序 - 测试 - bug记录 等等问题 laravel的启动过程解析 - lpfuture - 博客园 OAuth2 Server PHP 用 Laravel 搭建带 OAuth2 验证的 RESTful 服务 | Laravel China 社区 - 高品质的 Laravel 和 PHP 开发者社区 利用Laravel 搭建oauth2 API接口 附 Unauthenticated 解决办法 - 煮茶的博客 - SegmentFault 思否 使用 OAuth2-Server-php 搭建 OAuth2 Server - 午时的海 - 博客园 基于PHP构建OAuth 2.0 服务端 认证平台 - Endv - 博客园 Laravel 的 Artisan 命令行工具 Laravel 的文件系统和云存储功能集成 浅谈Chromium中的设计模式--终--Observer模式 浅谈Chromium中的设计模式--二--pre/post和Delegate模式 浅谈Chromium中的设计模式--一--Chromium中模块分层和进程模型 DeepMind 4 Hacking Yourself README.md update 20211011
Laravel China 简书 知乎 博客园 CSDN博客 开源中国 Go Further Ryan是菜鸟 | LNMP技术栈笔记 云栖社区-阿里云 Netflix技术博客 Techie Delight Linkedin技术博客 Dropbox技术博客 Facebook技术博客 淘宝中间件团队 美团技术博客 360技术博客 古巷博客 - 一个专注于分享的不正常博客 软件测试知识传播 - 测试窝 有赞技术团队 阮一峰 语雀 静觅丨崔庆才的个人博客 软件测试从业者综合能力提升 - isTester IBM Java 开发 使用开放 Java 生态系统开发现代应用程序 pengdai 一个强大的博主 HTML5资源教程 | 分享HTML5开发资源和开发教程 蘑菇博客 - 专注于技术分享的博客平台 个人博客-leapMie 流星007 CSDN博客 - 舍其小伙伴 稀土掘金 Go 技术论坛 | Golang / Go 语言中国知识社区
最新评论