[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[系统相关] 批处理无法在for中给变量累加赋值?

无法在for中给变量累加赋值?
请教各位一个问题?
写代码时发现cmd的一个奇怪显现,百思不得其解。
看下面的代码,先别运行,诸位能看出语法错误吗?
但第一次pause后,就会退出。。。
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. color 1f
  4. set "var=00000"
  5. for /l %%a in (1 1 10) do set var=!var!!var!
  6. echo !var!
  7. echo 这里可以运行。
  8. pause
  9. color cf
  10. set var=!var:0= 0 !
  11. echo !var!
  12. echo 这无法运行???
  13. pause
复制代码
原因有二
第一、 取消 set var=!var:0= 0 ! 这一句
第二、 for /l %%a in (1 1 10) do set var=!var!!var!
       这句中不能有多个的!var!,改为set var=000!var!就没事
       也就是这两句不能同时出现??
       郁闷。。。。。。
技术问题请到论坛发帖求助!

TOP

这个帖子的标题是不是该一下?

“变量的最大长度问题”比较合适
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

回复 29楼 的帖子

你这么一说好象可以把我差的那7b找回来,但是我把tt换成ttt还是一样的结果,
所以我猜测是把那7b留来记录set命令代码了,包含你提到的=,名等等。
其实 ,弄的这么晕,全怪微软。

[ 本帖最后由 myzwd 于 2009-2-25 12:01 编辑 ]

TOP

http://technet.microsoft.com/en-us/library/bb490954.aspx

The maximum individual environment variable size is 8192bytes.

The maximum total environment variable size for all variables, which includes variable names and the equal sign, is 65,536KB

实际上,第一句话后面也应该加上: which includes the variable name and the equal sign.

即:The maximum individual environment variable size is 8192bytes, which includes the variable name and the equal sign.
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

回复 26楼 的帖子

注意还要受到总的输入行长度的限制。
set var=value
即:set命令+空格[+引号]+变量名+等号+变量值[+引号]
这一条命令的总长度不能超过8192。
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

回复 27楼 的帖子

(cmd的set帮助说:它们都是要转换为数值计算的。)

请注意上下文!那说的是使用/a开关进行数学运算时才要转换。
set /?
...
/A 命令行开关指定等号右边的字符串为被评估的数字表达式。该表达式
评估器很简单并以递减的优先权顺序支持下列操作:
...
如果您使用任何逻辑或取余操作符, 您需要将表达式字符串用
引号扩起来。在表达式中的任何非数字字符串键作为环境变量
名称,这些环境变量名称的值已在使用前转换成数字。如果指定
了一个环境变量名称,但未在当前环境中定义,那么值将被定为
零。这使您可以使用环境变量值做计算而不用键入那些 % 符号
来得到它们的值。...


这里有一个以前说过多次的,常常让新手误解的地方:微软总喜欢把bat中的变量称为环境变量,很容易与系统环境变量这一概念混淆。
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

回复 23楼 的帖子

我试过了 你讲的完全对
我是用下面的例子做的
set tt=123a123
set tt=%tt:a=b%
-----------------------------
set tt=%tt:"a"="b"%
------------------------
结果是前一种有变化,后一种有变化。因为它们在运用时转换为数值的值不一样。
(cmd的set帮助说:它们都是要转换为数值计算的。)

TOP

回复 1楼 的帖子

我的例子:
@echo off
set tt
setlocal enabledelayedexpansion

for /l %%1 in (1 1 2323) do (

set tt=!tt!%%1)
set tt
pause
结果是tt为:123...2323,这是从1到2323的拼接。
这里里面的1位数有:9个
          2位数有:90个
          3位数有:900个
          4位数有:1324个
这样tt变量的总长度=9+2*90+3*900+4*1324=8185
------------------
还有7个字节就不知道跑哪去了。因为把tt换成ttt还是同样的结果。

The maximum individual environment variable size is 8192bytes.
最大的当环境变量的大小是8192b。我想这句话里面不应该包含名和等号才能解释上面的把tt换成ttt结果相同这个现象。因为它已经预留了给那些特殊符号的起指示作用的空间。值是不知道它是怎么留的,留的多少。
我猜测是7个字节。但是不能以上面一个例子来肯定。
The maximum total environment variable size for all variables, which includes variable names and the equal sign, is 65,536KB.
最大的全部环境变量的大小是,包括名字,等号,为65536kb
在计算全部变量的总大小时才考虑等号和名。


晕。管它是多少,反正关系不大。

[ 本帖最后由 myzwd 于 2009-2-24 19:48 编辑 ]

TOP

回复 24楼 的帖子

不知errorlevel的问题有什么进展,是不是涉及到for解释机制的问题了?

TOP

是变量类型不匹配还是输入行太长,把set "var=00000"中的0换成字母不就知道了吗?

根本不存在什么类型不匹配的问题。

而set var=!var:"0"=" 0 "! 显然没有进行任何替换操作。
命令行参考:hh.exe ntcmds.chm::/ntcmds.htm
求助者请拿出诚心,别人才愿意奉献热心!
把查看手册形成条件反射!

TOP

回复 21楼 的帖子

我上面已经说了啊,set var=!var:"0"=" 0 "!可以正确运行的原因是set之后的var和set之前的var一模一样,根本没有变化。长度没有发生变化,当然可以正确运行。其次解释一下为什么长度没有发生变化:我上面说到是引号自动对空格过滤。今天回来又验证一下,这种说法是不对的。引号没有过滤空格,长度不变的原因是set var=!var:"0"=" 0 "!中,set把"0"做为被替换的变量,在var中找不到"0",所以根本没有发生变化。举两个个例子:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set "var=123456789"
  4. set var=!var:"1"=" 5 "!
  5. echo !var!
  6. pause
复制代码
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. color 1f
  4. set "var=123456789"
  5. set var=!var:1=" 5 "!
  6. echo !var!
  7. pause
复制代码
你提出的:
【1】If you use any of the logical or modulus operators, you will need to
enclose the expression string in quotes.  给个例子:
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. set a=5
  4. set /a "a*=5,a<<=5"
  5. echo !a!
  6. pause
复制代码
这时需要把表达式用引号括起来,否则出错。
【2】The maximum total environment variable size for all variables, which includes variable names and the equal sign, is 65,536KB.
这句话我的理解为一个程序中所定义的所有环境变量所占用的内存空间不能超过64M。

TOP

回复 21楼 的帖子

5楼给出的链接就是微软的官方网站
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

但是

@echo off
setlocal enabledelayedexpansion
color 1f
set "var=00000"
for /l %%a in (1 1 10) do set var=!var!!var!
echo !var!
echo 这里可以运行。
pause
color cf
set var=!var:0= 0 !
echo !var!
echo 这无法运行???
pause


我把set var=!var:0= 0 !这里改为字符串的标准写法set var=!var:"0"= "0 "! 的确可以正确的执行啊。是不是可以这样将,批处理对于非标准的写法,有的能执行,有的不能。比如说rem 写出 ::就可以正常的执行。
   但是我做采用了标准写法 可以正常执行,这该怎么解释呢?按“长度”理论,我就没想明白。


   还有就是看cmd 的set帮助是这样说的:
------------------------------------------------------------
如果您使用任何逻辑或取余操作符, 您需要将表达式字符串用
引号扩起来。


*****在表达式中的任何非数字字符串键作为环境变量
名称,这些环境变量名称的值已在--------使用前-------转换成数字。*********


如果指定
了一个环境变量名称,但未在当前环境中定义,那么值将被定为
零。这使您可以使用环境变量值做计算而不用键入那些 % 符号
来得到它们的值。如果 SET /A 在命令脚本外的命令行执行的,
那么它显示该表达式的最后值。该分配的操作符在分配的操作符
左边需要一个环境变量名称。除十六进制有 0x 前缀, 八进制
有 0 前缀的,数字值为十进位数字。因此, 0x12 与 18 和 022
相同。请注意八进制公式可能很容易搞混: 08 和 09 是无效的数字,
因为 8 和 9 不是有效的八进制位数。

---------------------------------------------------------
   还有就是如果变量值的长度是8192那就是说浮点数采用的是16为二进制数其中2^13=8192,,这是你上面观点的论据,
但是微软的资料上找不到,你的论据啊。微软的资料上却可以明确找到---转换为数据这样的说发啊。
我是越想越糊涂。不知道怎么采对。
   

  我去看到了。长度理论有道理。
  • The maximum individual environment variable size is 8192bytes.
  • The maximum total environment variable size for all variables, which includes variable names and the equal sign, is 65,536KB.
  • 这两句话 第一句是 最大的单个 环境变量的 大小是 2^13bytes,从原文看,这里不应该包含其它符号。它没有这句话:“which includes variable names and the equal sign”, 从第二句话看,在计算全部变量的大小时要包含其它的符号,因为这时候有:which includes variable names and the equal sign, is 65,536KB. /第二句是:最大的全部 环境变量的大小之和是2^16=65536kb。按这个理论去想你的问题,又该如何解释 加了引号 就可以正常执行呢?
  • 我是这么想的不知道对不对:set "var=00000"
    for /l %%a in (1 1 10) do set var=!var!!var!   首先机器翻译这句话,第一次,var=2^3个0,因为是延迟环境变量,所以for中,在执行语句前,即机器在解释语句时,可以对环境变量的值进行传递,而对%%这种值机器在解释for时是不可以进行值的传递的, in(1 1 10) 说明要循环10次,每循环一次,var的长度就就增加8,相当于原有长度的基础上乘了2,10循环完,长度就变成了8*(2^10)=2^13=8192,所以你的程序,没有超过规定的长度,认为就是你的书写有错误,掉了引号。批处理这中松散的语句,不严格的写法,时对时不对。
  • 后来我把set "var=0000" 改为了set "var=000" ,程序中的其它不变,发现可以运行,这说明,我最初对英语
  • The maximum individual environment variable size is 8192bytes.的理解有误,这句话应该包含第二句话里面的
which includes variable names and the equal sign,这句话,如果算上其它的符号,变量真的是超过范围了。这正好解释了把把set "var=0000" 改为了set "var=000" 可以执行的原因了。
     因为 算上name和equal 变量的初始长度是6,不含引号,机器解释for时,var的长度是12,10次循环后长度是
12*(2^10)=12288>8192,所以报错。
     
    不过 ,还是得说说解释解释为什么 set var=!var:0=0 ! 改为这样set var=!var:"0"="0 "!又可以了

我明白了 ,长度理论是对的。支持!!!!!!

[ 本帖最后由 myzwd 于 2009-2-24 13:16 编辑 ]

TOP

我认为不是变量类型不匹配,批处理脚本语言也和大部分脚本语言一样,都具有“变量无关、解释执行”等特点。给个例子:
  1. @echo off
  2. set "a=123"
  3. set "b=456"
  4. set /a c=a+b
  5. echo !c!
  6. pause
复制代码

如果按照类型匹配的原则,set /a c=a+b应该报错才对啊。上述的set var=!var:0= 0 !改为set var=!var:"0"=" 0 "!,加引号后空格自动过滤,var依然不变,"0“没有替换为" 0 ",依然是"0",之所以可以运行的原因是因为变量和替换前一样,长度没有变化,没有超过最大长度。此题的根本原因仍是字符串长度问题!

TOP

返回列表