美文网首页Windows批处理指南
Windows 批处理脚本指南: 变量

Windows 批处理脚本指南: 变量

作者: ettingshausen | 来源:发表于2017-12-13 21:23 被阅读340次

    今天我们将介绍变量,这些变量在复杂点的批处理程序中都是必需的。变量的语法可能有点奇怪。:smile_cat:

    Variable Declaration


    DOS不需要声明变量。未声明/未初始化变量的值是空字符串或""。大多数人喜欢这样,因为它减少了需要编写的代码量。就我个人而言,我喜欢在使用变量之前声明一个变量,因为它可以捕获了一些简单的错误,比如变量名拼写错误。

    Variable Assignment


    使用 SET 命令为一个变量赋值。

    SET foo=bar
    

    注意:不要在名称和值之间使用空格;SET foo = bar 将不起作用,但 SET foo=bar 就可以。

    /A 开关支持算数操作。这是一个有用的工具,如果您需要验证该用户输入是一个数值。

    SET /A four=2+2
    4
    

    一般的惯例,变量经常使用小写名称,系统变量(环境变量)一般是大写。这些环境描述了在您的系统中哪里可以找到某些东西,例如 %TEMP%,它是临时文件的路径。DOS是不区分大小写的,所以这个惯例并不是强制的,但是让脚本更容易阅读或者故障排除,倒是个好主意。

    警告:SET终覆盖任何现有变量。在编写脚本时,先验证下是否覆盖了系统范围的变量。ECHO %foo%可以快速确认 foo 是不是一个现有的变量。例如,很容易将一个变量命名为 “temp”,但这将会改变广泛使用的 “%temp%” 环境变量的含义。DOS包含一些“动态”的环境变量,它们的行为更像是命令。这些动态变量包括 %DATE%%RANDOM%%CD%。最好不要覆盖这些动态变量。

    Reading the Value of a Variable


    在大多数情况下,可以通过%运算符将变量名括起来读取变量值。下面的示例将变量 foo 的当前值打印到控制台输出。

    C:\> SET foo=bar
    C:\> ECHO %foo%
    bar
    

    在一些特殊的情况下,变量不使用 % 这种语法,我们将在本系列后面讨论这些特殊情况。

    Listing Existing Variables


    SET 命令不加参数,会输出所有的变量到控制台。这些变量大多数是环境变量,比如 %PATH% 或者 %TEMP%

    无参数的SET命令

    注意:调用SET将列出当前会话的所有常规(静态)变量。不包括动态环境变量,如 %DATE%%CD%。在SET帮助文本的末尾列出这些动态变量,可以通过调用 SET /? 来查看。

    %CD% - 扩展到当前目录字符串。
    %DATE% - 用跟 DATE 命令同样的格式扩展到当前日期。
    %TIME% - 用跟 TIME 命令同样的格式扩展到当前时间。
    %RANDOM% - 扩展到 0 和 32767 之间的任意十进制数字。
    %ERRORLEVEL% - 扩展到当前 ERRORLEVEL 数值。
    %CMDEXTVERSION% - 扩展到当前命令处理器扩展版本号。
    %CMDCMDLINE% - 扩展到调用命令处理器的原始命令行。
    %HIGHESTNUMANODENUMBER% - 扩展到此计算机上的最高 NUMA 节点号。

    Variable Scope (Global vs Local)


    默认情况下,变量对整个命令提示符会话是全局的。调用SETLOCAL命令,将变量变为局部变量。任何局部变量赋值在调用ENDLOCALEXIT,或者当执行到达脚本中的文件结尾(EOF)时都会恢复。

    本示例演示如何在名为HelloWorld.cmd的脚本中更改名为foo的现有变量。 当脚本退出时,%foo%会恢复的原始值。

    HelloWrold.cmd

    SETLOCAL
    SET v=Local Value
    ECHO %v%
    
    变量恢复

    一个真实的例子应该是修改系统的%PATH%环境变量。

    PATH: 存储了执行命令时搜索的目录列表。

    修改系统Path环境变量

    Special Variables


    有些特殊情况,变量的使用有些小差异。在命令行中给脚本传递的参数也是变量,但是不要使用%var%语法。 而是用%跟一个0-9的数字读取每个参数,数字代表参数的位置。 在稍后的创建函数的例子中,将会看到同样的风格。

    还有一个使用!的变量语法,就像!var! 这是一种称为延迟扩展的特殊情况。 当我们讨论条件(if / then)和循环时,将会讲解更多关于延迟扩展的内容。

    Command Line Arguments to Your Script


    你可以使用特殊的语法读取传递给脚本的命令行参数。 语法是一个单一的%字符,后面是从0到9的参数的序号位置。零序参数是批处理文件本身的名称。 所以我们脚本HelloWorld.cmd中的变量%0将是“HelloWorld.cmd”。

    命令行的第一个非空参数就是 %1, 第二个就是%2 ……, 第九个就是%9

    Note: DOS确实支持9个以上的命令行参数,然而,你不能直接读取第9个之后参数。这是因为特殊变量语法不能识别%10或更高。 实际上%10,它只识别到%1, 0 作为一个字符被拼接到后边。

    通过一个例子来测试下,写几个脚本命名为 arguments.cmd, 内容如下

    echo %1
    echo %10
    
    不能识别%10
    从运行结果来看,%10实际上是: 第一个参数 + 0

    使用SHIFT命令从参数列表中弹出第一个参数,这使得所有的参数都向左移动,这样第十个参数就可以通过%9来获取了。在循环的部分,将会详细讲解这部分内容。

    Tricks with Command Line Arguments


    命令行参数还支持一些非常有用的可选语法,针对文件路径参数,可以解析作为命令行参数的文件的路径、时间戳或大小。这个超级有用的特性文档有点难找 :pouting_cat:,运行 for /?,在页面的最末尾。

    • %~I从第I个命令行参数中删除引号,在处理文件路径参数时非常有用。之前讲过,带空格的路径需要用引号括起来,但是多次括起来就会导致错误。这里的I可以事0~9的整数。

    • %~fI 展开完整路径
      例如 args.cmd

      echo %~f1
      

      调用

      args.cmd .\adoble
      

      输出:C:\Users\Edward\Desktop\Adobe

    • %~fsI 与上边的类似,s 选项会生成一个 DOS 8.3[1]的短路径,例如:C:\Program Files缩写为 C:\PROGRA~1。在使用一些不处理空格的第三脚本,这个技巧很实用啊。 :wink:

    • %~dpII个文件路径参数的完整父级路径。几乎在每个批处理脚本中,我都用这个技巧来确定脚本的位置。 SET parent=%~dp0通过这个用法,可以输出脚本的所在路径。

    • %~nxII个文件路径参数的文件名(包括扩展名)。类似%0, 我也经常使用这个技巧来确定运行时脚本的名字。如果需要输出消息给用户,我喜欢在消息前面加上脚本的名字,像这样ECHO %~n0: 输出的消息,而不是直接输出ECHO 输出的消息。这样做的好处是,用户知道这个消息是从哪个脚本中输出的。如果你花了几个小时的时间为了确定错误消息是从哪个脚本输出的,是不是很崩溃?:laughing:

    Some Final Polish


    我总是将这些命令包含在批处理脚本的顶部:

    SETLOCAL ENABLEEXTENSIONS
    SET me=%~n0
    SET parent=%~dp0
    

    SETLOCAL命令能保证脚本在退出之后不覆写任何现有的变量。ENABLEEXTENSIONS[2],是SETLOCAL的一个参数,这是一个非常有用的特性,称之为启动或停用命令处理器扩展名。别问为什么真的很有用 :joy:
    me变量存储了脚本的名称(不包含扩展名)。这样就能很方便的给输出的消息加上前缀ECHO %me%: 输出的消息
    parent存储了脚本的所在目录,这样可以很容易的给同一目录下的其他文件拼接出完整的路径。

    参考资料


    1. 8.3 filename

    2. Determines whether the extensions to the command processor (Cmd.exe)

    相关文章

      网友评论

        本文标题:Windows 批处理脚本指南: 变量

        本文链接:https://www.haomeiwen.com/subject/pbozixtx.html