Board logo

标题: [原创] 批处理中set /a 极大的误区 [打印本页]

作者: defanive    时间: 2009-1-17 15:30     标题: 批处理中set /a 极大的误区

关于 set /a 中极大的误区,几乎所有的批处理教材中都有这个错误,误导了至少80%的人!

这句:set /a a+=1
一切教学资料上的解释都是:与
set /a a=%a%+1
相等同!

那么我们做一个有趣的实验:
  1. @echo off
  2. set a=0
  3. for /l %%b in (1,1,5) do set /a a+=1
  4. echo a=%a%
  5. pause
复制代码
得到的输出是:
a=5
请按任意键继续. . .

那么根据教材所说的,等同于 set /a a=%a%+1 ,我们测试一下效果:
  1. @echo off
  2. set a=0
  3. for /l %%b in (1,1,5) do set /a a=%a%+1
  4. echo a=%a%
  5. pause
复制代码
得到的输出是:
a=1
请按任意键继续. . .

教材和资料都错了!
正确的解释应是:set /a a+=1 与 set /a a=a+1 对等!
多了两个%括住就造成的极大的错误!

正确对等的代码是:
@echo off
set a=0
for /l %%b in (1,1,5) do set /a a=a+1
echo a=%a%
pause


输出:
a=5
请按任意键继续. . .

当然,无聊的话下面这样写也是对等的,当然及不简便:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set a=0
  4. for /l %%b in (1,1,5) do set /a a=!a!+1
  5. echo a=%a%
  6. pause
复制代码
开启变量延迟,用!括住也是正确的



那么,请大家看完这篇东西之后,记住不要再犯同样的错误,同样不要再去误导他人:
set /a a+=1
不等于
set /a a=%a%+1
应等于
set /a a=a+1
作者: tireless    时间: 2009-1-17 16:46

预处理的关系吧,与 set 无关。

set a=0
for /l %%b in (1,1,5) do set /a a=%a%+1

当读取以上整个 for 语句后,执行语句前进行了预处理,最后实际执行的是:

for /l %%b in (1,1,5) do set /a a=0+1

[ 本帖最后由 tireless 于 2009-1-17 18:35 编辑 ]
作者: defanive    时间: 2009-1-17 18:02

通常的讲,set /a a+=1正确的应该是set /a a=a+1而不是set /a a=%a%+1

实际上for这五次set /a a=%a%+1的变量设置都被延迟了

但是set /a a=a+1是set /a的一个特性,设置的变量会立即生效

所以set /a a+=1就结果来看,是立即生效的,对应的应该是set /a a=a+1

的确不关set的事,关教材资料的事
作者: pusofalse    时间: 2009-1-17 18:15

特性如此~
  1. If you use any of the logical or modulus operators, you will need to
  2. enclose the expression string in quotes.  Any non-numeric strings in the
  3. expression are treated as environment variable names whose values are
  4. converted to numbers before using them.  If an environment variable name
  5. is specified but is not defined in the current environment, then a value
  6. of zero is used.  This allows you to do arithmetic with environment
  7. variable values without having to type all those % signs to get their
  8. values.
复制代码
This allows you to do arithmetic with environment
variable values without having to type all those % signs to get their
values.
set /a a=%a%+1实际执行的是set /a a=+1而不是set /a a=0+1
set /a a=a+1 才是set /a a=0+1,但在for中它是会实时改变的。
作者: BBCC    时间: 2009-1-17 21:12

所以说,微软在这方面做得很乱,两个标准……
作者: sjzong    时间: 2009-4-14 15:42

哦!谢谢楼主,以后要注意了!
作者: 鳌头七队    时间: 2011-6-1 19:32

是批处理的变量延迟搞的鬼
作者: Demon    时间: 2011-6-1 19:49

那些垃圾教程只会误人子弟罢了
作者: qzwqzw    时间: 2011-6-1 21:25

说实话,
没有看到哪里的教材是这样写的
楼主提及“几乎所有的批处理教材”
不知是否能够例举一二?
作者: Batcher    时间: 2011-6-1 23:31

这个帖子也许是楼主刚接触批处理的时候写的,大家淡定了。
作者: applba    时间: 2011-6-2 04:52

set命令能够自行识别变量名,并完成变量值的替换。
还有一个用法类似,if defined varname,也不需要%。
作者: szylmzs    时间: 2011-6-2 09:47

应该是变量延迟的问题
作者: cjiabing    时间: 2011-6-3 21:46

哈哈,我比较怕数学,没有上过当,不过现在经常用到set /a a+=1,其它两个用得少。
写教材一定要自己亲自测试过代码才可以引用,否则害人不浅!~
作者: andy七少    时间: 2011-6-9 12:40

for中的%a%只会应用上一个语句set设置的环境变量
还是变量延迟高的鬼嘛!
作者: guaiwu    时间: 2011-10-4 16:12

有心提醒了。   心意领会了
作者: Fantasys    时间: 2011-10-12 17:59

我觉得官方解释不能说错,只是在批处理有些特别的地方罢了。开启变量延迟就可以了,说明它解释还是对的。
作者: 网上邻居    时间: 2016-3-17 14:41

预处理机制而已。
作者: 小程936    时间: 2016-6-17 09:38

set /a x=a,a=b,b=x
可以交换a和b的位置,你怎么看?
作者: ai20110304    时间: 2016-10-20 23:33

谢谢 分享     
作者: tiger999    时间: 2017-1-27 15:07

QAQ LZ不要误导别人啊,吓得差点误解了我习惯了3年的知识
这是因为变量延迟的问题,这和所谓的%%没有关系
你只需要加一个setlocal enabledelayedexpansion,把%换成!就好了,QAQ
作者: ShenMian    时间: 2018-2-18 00:31

这是延迟变量的问题,而不是什么教程乱讲。若考虑延迟变量应该写为set /a a+=1等价于set /a a=!a!+1,如果没有开启本地自动化操作则是错误的语句。所以set /a a=%a%+=1并没有错误。
作者: ai20110304    时间: 2018-8-29 23:29

回复 11# applba


    大侠说到点子上了。细心点发现
作者: ai20110304    时间: 2018-8-29 23:31

回复 1# defanive


    这个复合运算符隐含延迟变量的功能。就像java中复合运算符隐式一个强制类型转换




欢迎光临 批处理之家 (http://bbs.bathome.net/) Powered by Discuz! 7.2