批处理命令___实践浅谈

关于环境变量延迟扩展,使用set /?可以查看到部分说明,不过考虑到其粗劣的翻译水平,建议在查看之前,首先chcp 437切换为英文查看原英文说明。鉴于文中已说得十分详尽,而且有数个代码示例,应该不难理解。在此仅略作一些补充。

      在许多可见的官方文档中,均将使用一对百分号闭合环境变量以完成对其值的替换行为称之为“扩展(expansion)”,这其实是一个第一方的概念,是从命令解释器的角度进行称谓的,而从我们使用者的角度来看,则可以将它看作是引用(Reference)、调用(Call)或者获取(Get)。

      而命令解释器是扩展环境变量的行为大致如下:首先读取命令行的一条完整语句,在进行一些先期的预处理之后,命令被解释执行之前,会对其中用百分号闭合的字符串进行匹配,如果在环境空间中找到了与字符串相匹配的环境变量,则用其值替换掉原字符串及百分号本身,如果未得到匹配,则用一个空串替换,这个过程就是环境变量的“扩展”,它仍然属于命令行的预处理范畴。

      而一条“完整的语句”,在NT的命令解释器CMD中被解释为“for if else”等含有语句块的语句和用“& | && ||”等连接起来的复合语句。

      因此,当CMD读取for语句时,其后用一对圆扩号闭合的所有语句将一同读取,并完成必要的预处理工作,这其中就包括环境变量的扩展,所以在for中的所有语句执行之前,所有的环境变量都已经被替换为for之前所设定的值,从而成为一个字符串常量,而不再是变量。无论在for中将那些环境变量如何修改,真正受到影响的只是环境变量空间,而非for语句内部。
      
      而为了能够在for语句内部感知环境变量的动态变化,CMD设计了延迟的环境变量扩展特性,也就是说,当CMD读取了一条完整的语句之后,它不会立即执行变量的扩展行为,而会在某个单条语句执行之前再进行扩展,也就是说,这个扩展行为被“延迟”了。

      延迟环境变量扩展特性在CMD中缺省是关闭的,开启它的方法目前有两个:一是CMD /v:off此处说法有误,应为 CMD /v:on——namejm 注),它会打开一个新的命令行外壳,在使用exit退出这个外壳之前,扩展特性始终有效,常用于命令行环境中;二是setlocal EnableDelayedExpansion,它会使环境变量的修改限制到局部空间中,在endlocal之后,扩展特性和之前对环境变量的修改将一同消失,常用于批处理语句中。

批处理命令 : FOR浅谈

FOR这个命令比较特殊是一个循环执行命令的命令,同时FOR的循环里面还可以套用FOR在进行循环

在批处理中FOR的命令如下:
            FOR [%%c] IN (set) DO [command] [arguments]
            在命令行中命令如下:
            FOR [%c] IN (set) DO [command] [arguments]
            常用参数:
            /L 该集表示以增量形式从开始到结束的一个数字序列。因此,(1,1,5) 将产生序列 1 2 3 4 5,(5,-1,1) 将产生序列
            (5 4 3 2 1)。

            FOR /R [[drive:]path] %%variable IN (set) DO command [command-parameters]
            /R 检查以 [drive:]path 为根的目录树,指向每个目录中的 FOR 语句。如果在 /R 后没有指定目录,则使用当前目录。

            如果集仅为一个单点(.)字符,则递归枚举该目录树。比/D功能强大!

            FOR /D %%variable IN (set) DO command [command-parameters]

            /D 如果集中包含通配符,则指定与目录名匹配,而不与文件名匹配。仅枚举当前路径下的目录名字
           
/F 从指定的文件中读取数据作为变量
            eol=c - 指一个行注释字符的结尾(就一个)
            skip=n - 指在文件开始时忽略的行数。
            delims=xxx - 指分隔符集。这个替换了空格和跳格键的默认分隔符集。
            tokens=x,y,m-n - 指每行的哪一个符号被传递到每个迭代的 for 本身。这会导致额外变量名称的分配。m-n格式为一个范围。通过 nth 符号指定
            mth。如果符号字符串中的最后一个字符星号,那么额外的变量将在最后一个符号解析之后分配并接受行的保留文本。
            usebackq - 指定新语法已在下类情况中使用:在作为命令执行一个后引号的字符串并且一个单引号字符为文字字符串命令并

            允许在filenameset中使用双引号扩起文件名称。

            usebackq - 使用后引号(键盘上数字1左面的那个键`)。

            未使用参数usebackq时:file-set表示文件,但不能含有空格

            双引号表示字符串,即"string" 。单引号表示执行命令,即'command'

            使用参数usebackq时:file-set和"file-set"都表示文件

            当文件路径或名称中有空格时,就可以用双引号括起来

下面来看一个例子:
            FOR /F "eol=; tokens=2,3* delims=, " %i in (myfile.txt) do @echo %i %j %k
            会分析 myfile.txt 中的每一行,忽略以分号打头的那些行,将每行中的第二个和第三个符号传递给 for
            程序体;用逗号和/或空格定界符号。请注意,这个 for 程序体的语句引用 %i 来取得第二个符号,引用 %j 来取得第三个符号,引用
            %k来取得第三个符号后的所有剩余符号。对于带有空格的文件名,您需要用双引号将文件名括起来。为了用这种方式来使用双引号,您还需要使用
            usebackq 选项,否则,双引号会被理解成是用作定义某个要分析的字符串的。
            %i 专门在 for 语句中得到说明,%j 和 %k 是通过tokens= 选项专门得到说明的。您可以通过 tokens= 一行指定最多
            26 个符号,只要不试图说明一个高于字母 'z' 或'Z' 的变量。请记住,FOR 变量名分大小写,是通用的;而且,同时不能有52个以上都在使用中。
            您还可以在相邻字符串上使用 FOR /F 分析逻辑;方法是,用单引号将括号之间的 filenameset
            括起来。(最好替换用shift命令来做参数解析)这样,该字符串会被当作一个文件中的一个单一输入行。

            最后,您可以用 FOR /F 命令来分析命令的输出。方法是,将括号之间的
            filenameset 变成一个反括字符串。该字符串会被当作命令行,传递到一个子CMD.EXE,其输出会被抓进内存,并被当作文件分析。因此,以下例子:
            FOR /F "usebackq delims==" %i IN (`set`) DO @echo %i会枚举当前环境中的环境变量名称。
            以下列举一个简单的例子,他将说明参数/L和没有参数的区别:
            删除文件1.TXT 2.TXT 3.TXT 4.TXT 5.TXT
            例:
            ECHO OFF
            FOR /L %%F IN (1,1,5) DO DEL %%F.TXT
            或
            FOR %%F IN (1,2,3,4,5) DO DEL %%F.TXT
            以上2条命令执行的结果都是一样的如下:
            C:/>DEL 1.TXT
            C:/>DEL 2.TXT
            C:/>DEL 3.TXT
            C:/>DEL 4.TXT
            C:/>DEL 5.TXT

           以下是我的例子:程序想对输入参数"%5 "a_keyword b_keyword c_keyword"所含有的关键字做递归处理,但运行发生异常,原因是不正确使用for /f %%i in (' '),应该是错误地传入参数%%i,譬如example.cmd "a.txt  b.txt  c.txt",%var%值为"a.txt  b.txt  c.txt"不是期望的a.txt  b.txt  c.txt,第二次调用for %var%值为b.txt c.txt",导致错误退出。

命令:echo 1 & echo 2 & echo 3

可以写成:

(

echo 1

echo 2

echo 3

)

上面两种写法效果一样,这两种写法都被视为是一条命令行。 注意:这种多条命令被视为一条命令行时,如果其中有变量,就涉及到变量延迟的问题。

@echo off

 setlocal enabledelayedexpansion

 set a=4

 set a=5 & echo !a!

 pause

结果:5

解说:启动了变量延迟,得到了正确答案。变量延迟的启动语句是“setlocal enabledelayedexpansion”,并

且变量要用一对叹号“!!”括起来(注意要用英文的叹号),否则就没有变量延迟的效果。

分析一下例2,首先“setlocal enabledelayedexpansion”开启变量延迟,然后“set a=4”先给变量a 赋值为

4,“set a=5 & echo !a!”这句是给变量a 赋值为5 并输出(由于启动了变量延迟,所以批处理能够感知到动

态变化,即不是先给该行变量赋值,而是在运行过程中给变量赋值,因此此时a 的值就是5 了)。

再举一个例子巩固一下。

 @echo off

 setlocal enabledelayedexpansion

 for /l %%i in (1,1,5) do (

 set a=%%i

 echo !a!

 )

 pause

结果:

1

2

3

4

5

解说:本例开启了变量延迟并用“!!”将变量扩起来,因此得到我们预期的结果。如果不用变量延迟会出现什

么结果呢?结果是这样的:

ECHO  处于关闭状态。

ECHO  处于关闭状态。

ECHO  处于关闭状态。

ECHO  处于关闭状态。

ECHO  处于关闭状态。

即没有感知到for 语句中的动态变化。

提示:在没有开启变量延迟的情况下,某条命令行中的变量改变,必须到下一条命令才能体现。这一点也

可以加以利用,看例子。

例:交换两个变量的值,且不用中间变量

@echo off

:: 目的:交换两个变量的值,但是不使用临时变量

set var1=abc

set var2=123

echo  交换前:  var1=%var1% var2=%var2%

set var1=%var2%& set var2=%var1%

echo  交换后:  var1=%var1% var2=%var2%

pause


 

例:

dir c:/;d:/;e:/1.txt

以上命令相当于

dir c:/

dir d:/

dir e:/1.txt

其中文件e:/1.txt不存在,但e盘存在,有错误提示,但命令仍会执行。

为什么?如果目标路径不存在,则终止执行;如果路径存在,仅文件不存在,则继续执行

 

shift命令转换为对输入参数%5 "a_keyword" %6 ” b_keyword“ %7 ”c_keyword"...处理

整体循环
            for /l %%a in (0,1,255) do for /l %%b in (0,1,255) do for /l %%c in
            (1,1,254) do for /f "tokens=1,2*" %%e in (userpass.txt) do net use
           
//%1.%%a.%%b.%%c/ipc$ %%e /u:%%f
            上面的命令为1条命令。大家可以看出该命令使用了4个FOR来套用的。用法为:C:/>TEST.BAT 218
            当输入518回车后该命令会由第1个for取初始值0为%%a然后继续取第2个for的初始值0为%%b继续取第3个for的初始值1为%%c

            最后一个for是将userpass.txt中的第一段字符作为密码%%e第二段字符作为用户名%%f最后执行命令
            (这里我把上面的值都带进去,设密码为123 用户名为 abc)
            net usr
//218.0.0.1/ipc$ 123 /u:abc

 

FOR命令中的变量

~X - 删除任何引号("),扩展 %X . X为for命令任意变量

%~fX - 将 %X 扩展到一个完全合格的路径名

%~dX - 仅将 %X 扩展到一个驱动器号

%~pX - 仅将 %X 扩展到一个路径

%~nX - 仅将 %X 扩展到一个文件名

%~xX - 仅将 %X 扩展到一个文件扩展名

%~sX - 扩展的路径只含有短名

%~aX - 将 %X 扩展到文件的文件属性

%~tX - 将 %X 扩展到文件的日期/时间

%~zX - 将 %X 扩展到文件的大小

%~$PATH:I - 查找列在路径环境变量的目录,并将 %I 扩展 到找到的第一个完全合格的名称。如果环境变量名 未被定义,或者没有找到文件,此组合键会扩展到 空字符串

eg:

创建文件:

 在当前目录下创建a.txt

     cd. >a.txt  %当前路径下创建文件a.txt并在开头添加一空行%

    echo ::now we do sth to this file "a.txt" >a.txt % 向文件写入注释%

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值