加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

批处理脚本高级编程技巧----变量嵌套

(2011-10-22 10:53:00)
标签:

杂谈

分类: 批处理

一,为什么要使用变量嵌套?
  1,可提高代码的效率
  2,可以缩减代码
二,批处理变量的种类
  1, %0~%9 , %*:   批处理运行的命令行参数,在代码行预处理时扩展,可视为最高优先级扩展。

    如果存在变量:
12a=###
!a=$$$
a=aaa

echo;%12a%
得到结果为:第一个参量+2a

echo;%!a%!
得到结果为:$$$

2, %var%:  在代码行预处理时扩展,其实与%1~%9 ,%*是同时扩展取值的,
    但是%1%得到的只有可能是参量值,绝不可能得到变量值,所以视为次优先级扩展,

   ********** 预处理问题 **********
    要很好的理解%号变量,需要知道一点,预处理一次是读取一组来进行的  
      如:
  
        [1]
        set a=aa&echo %bb%

        [2]
        if aa==%bb% (
                echo 等
        )

        [3]
        (
                echo %aa%
                echo %bb%
        )
        上面就是所“组”的形式。

      还要知道:%号变量在预处理读取代码行时已经扩展了
        例如: set kh=)
(echo %kh%&pause
echo bb
)复制代码因为%kh%扩展了,其值中的 ")" 与前面的 "(" 形成了一组代码,其实只读取了一行,
        运行代码遇到pause暂停后,修改bat文件, 把echo bb改为:echo cc,并保存后,再按键继续可见到显示的是"cc"
   ********** 预处理问题 **********

  3, for()变量: %%a %%1 %%中 等形式均可使用,

    虽然 %%a%或者%%1 等形式得到的还是for 变量的值,而不是作为:%a% %1 扩展,
    为什么呢?
    因为预处理在处理%var%形式变量时,是从左到右以两个%号作为一组变量的,而以%+一个数字作为一组参量的,
    还有一点就是如果一组%号的两个%号间没有其它字符时,将留下一个%号,
    所以是要将for()变量视为第三优先级,
    另外变量%var% 及%1扩展后的值里面,如果含有有效的for ()变量%a的话,该值中的%a 会得到for()变量再次扩展
    更说明了for()变量要比%var% %0~%9,%*要低一级
    这个例子是变量的嵌套扩展的一种形式,
    其实for ()的变量名应该是:经预处理后的一个 %+一个字符,以cmd批处理脚本里面,可以是数字,字母,或字符和汉字都可以。
    for变量仅在该组for()内有效,并向下一级子for ()继承
    如果父级for()与子级for()有相同的有效变量时,得到的是当前级的扩展值
例如: for /f "tokens=1,2,3" %%a in ("aa ab ac") do (
   for /f "tokens=1,2,3" %%b in ("$a $b $c") do (
      echo;%%a-%%b-%%c-%%d &rem 结果为:aa-$a-$b-$c
     rem 而不是:aa-ab-ac-$c
   )
      echo;%%a %%b %%c %%d &rem 结果为:aa-ab-ac-
)复制代码4,!var!:  变量延迟打开时有效,在命令运行时扩展,可视为四级优先级,
为什么要这么认为呢?
    如果for()变量扩展后,重新组成的表达式中,含有!号的话,命令运行时会再次进行!var!的取值扩展
这也是变量嵌套扩展的一种形式
     !var!变量,在一对setlocal ... 和endlocal内有效,并向下一级子环境继承

  5,set/a 运算命令变量,这可以说最低级的变量扩展了,就连!var!变量也扩展后,
     如果得到的是以非数字及非运行符开头的话,就会再次进行变量扩展之后才执行运算。

三、只有了解变量扩展的优先级,才可能理解变量嵌套的用法。  
    变量嵌套扩展的方式有:
*** 注意:要开启变量延迟,否则!var!变量无从谈起 ***
    1,先%1或%var% 再 !var!
只要%1或%var%扩展的值中含有或和旁边的字符组合后含有:!var!,!var:n=m!,!var:~2,2! 等形式
就会再次进行!号变量的扩展
        例如: setlocal enabledelayedexpansion
set aa=bb
set abb=##
echo 程序文件名:%0
echo 嵌套扩展:!a%aa%!
pause复制代码2,先%1或%var% 再 for ()%a
只要%1或%var%扩展后的值里面,含有有效的for ()变量%a的话,该值中的%a 会再次得到for()变量扩展
        例如: set #=%%a
for %#% in (aa bb cc) do (echo;%#%)
pause复制代码3,先for()%a 再!var!
只要for()%a扩展的值中含有或和旁边的字符组合后含有:!var!,!var:n=m!,!var:~2,2! 等形式
就会再次进行!号变量的扩展,这也就是为什么开启了变量延迟后,会丢失!号的原因。
        例如: set #aa=$a
set #bb=$b
set #cc=$c
for %%a in (aa bb cc) do (echo;%%a : !#%%a!)
pause复制代码4,先%1或%var% 再 for ()%a  再!var!
也就是第2+第3种用法的

        例如: setlocal enabledelayedexpansion
set #=%%a
set aaa=##a
set abb=##b
set acc=##c
for %#% in (aa bb cc) do (echo %%a : a%#% : !a%#%!)
pause复制代码5,多级嵌套:先%1或%var% 再 for ()%a  再!var! 再for ()%b 再!var!
主要是for ()%a 和!var!间的循环嵌套,看例子: for %%a in (aaa_$a bbb_$b ccc_$c) do (
    set str=%%a
for /f "tokens=1,2 delims=_" %%b in ("!str!") do (         rem !str!作为for /f 的字符串表达式
  echo;[2f] %%b+%%c
  set %%c=%%a        &rem 第一次循环时:相当于set $a=aaa_$a
  for /f "tokens=1,2 delims=_" %%1 in ("!%%c!") do ( &rem 相当于:!$a!作为for /f 的字符串表达式
   echo;[3f] %%1=%%2
   
)
)
set $           &rem 显示变量,方便理解复制代码** 这点是变量嵌套的最巧用法,是提高批处理脚本的关键 **
    6,运算命令变量,就是在其它变量都扩展完了之后,还可以再进行扩展一次。 set a=100
set b=a
set "c=^!b^!*2"
set/a d=%c%+10复制代码代码中:%c% => !b!*2 => a*2 => 100*2 所以结果进行了以下运算: set /a d=100*2+10复制代码7,管道方式:

set aa=d 100 &((echo;%%aa%%&echo;q)|debug)

虽然是在同一行,也没有用到call ,但是%%a%%扩展成了d 100
原因是(echo;%%a%%&echo;q)是在批处理外运行的,并且通过管道把显示值传给后面的命令debug 作为输入行。

    8,效率较低级的call 方式变量嵌套,相当于从第1种方式到第5种方式再循环一次。(有所重复,就不详述)

四、变量嵌套扩展的实际应用。
    1,if 用法 set "str= help open quit run "
set in=输入:
if "!str: %in% =!" neq "!str!" goto :m_%in%
:m_help
:m_open
:m_quit
:m_run复制代码2,for 用法: set n1=姓名:!@n!     性别:!@xb!
set n2=学历:!@xl!     年龄:!@g!
set n3=民族:!@m!     体重:!@tz!
::前面先不要开变量延迟
setlocal enabledelayedexpansion
for /f "tokens=1-6" %%1 in ("benton 男 中专 18岁 汉 90kg") do (
set @n=%%1&set @xb=%%2&set @xl=%%3&set @g=%%4&set @m=%%5&set @tz=%%6
)
for /l %%a in (1,1,3) do (
for %%b in (!n%%a!) do (echo;%%b)
)
set n  &rem 查看变量方便理解复制代码

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有