Board logo

标题: [转贴] 浅谈批处理脚本的编写 - 3.通用性篇 [打印本页]

作者: HAT    时间: 2011-12-17 14:00     标题: 浅谈批处理脚本的编写 - 3.通用性篇

3.通用性篇
  代码的通用性是衡量代码价值的重要标准之一,一个不考虑通用性的代码,可能产生不可预料的致命后果。
  当然通用是相对的,我们所谓的通用,一般是在常见环境下的通用,再通用的代码也有它不通用的环境。
3.1 要考虑环境的差别
  在不同系统环境下,代码的结果是有差异的,所以一般要尽量选用通用性最强的代码。
【code1】
  1. timeout /t 3 /nobreak
  2. choice /c yn
  3. if %errorlevel%==1 set /p=   test<nul
  4. ::延时 3 秒,等待用户输入,如果为 y 则不换行输出 "   test"
  5. ::在 xp 以下不自带 timeout.exe,而 choice.exe 在 xp 中也不是默认配置,而在 xp 以上的系统中,set /p 会忽略提示语句中为首的半角空格。
复制代码

【code2】
  1. ping 127.1 >nul
  2. set /p input=[y,n]?
  3. if %errorlevel%==y set /p=@    test<nul
  4. ::为了兼容 xp,这里用 ping 代替 timeout 进行延时,而用 set /p 代替 choice,并且在 set /p 中加入退格符,避免空格开头在 vista/win7 下出错
复制代码


3.2 要考虑输入中含有特殊字符
【code1】
  1. @echo off&setlocal enabledelayedexpansion
  2. for /f "delims=" %%a in (1.txt) do (
  3.    if !last! neq %%a echo %%a
  4.    set last=%%a
  5. )
  6. ::排除重复的相邻行,看似简单,但却隐含了很大的漏洞,如果 1.txt 中存在以 ; 为首的行将被忽略(默认情况下 eol=;),另外,假如某一行包含 ! 结果将出错
复制代码

【code2】
  1. @echo off
  2. for /f "delims=" %%a in ('findstr /n . 1.txt') do (
  3.    rem 用 findstr /n 给输入加行号,防止 ; 开头的行被忽略
  4.    set str=%%a
  5.    setlocal enabledelayedexpansion
  6.    rem 在将行内容设为 str 变量后再打开变量延迟,避免引用 %%a 时由于其中存在 ! 号而出错
  7.    if !last! neq !str:*:^=! echo !str:*:=!
  8.    rem 当上一行内容与当前行内容(去掉行号后的)不相同则输出当前行
  9.    for /f "delims=" %%b in (""!str:*:^=!"") do endlocal&set last=%%~b
  10.    rem 关闭变量延迟,并通过 for /f 保留 !str:*:=! 的值赋予 last 变量,并通过加引号、去引号的技巧再次防止以 ; 为首的行被忽略
  11. )
  12. ::排除重复的相邻行,虽然比较复杂繁琐,但是在不明背景的情况下,必须要考虑到方方面面
  13. ::这种严谨的态度是出于周全的考虑,一个人的水平从他代码是否严谨就可以略窥一二。
复制代码


3.3 考虑到命令与输入的细节特征
  这和 3.2 的内容有部分重复,在此只讲不重复的部分
【code1】
  1. for /l %%a in (0 1 9) do set str=!str:%%a=!
  2. ::去除str变量中所有数字,但是当str变量中只有数字且没有9的时候将出错。
复制代码

【code2】
  1. set str=9!str!
  2. for /l %%a in (0 1 9) do set str=!str:%%a=!
  3. ::给变量附加一个 9,避免当str变量已经为空时仍进行变量替换,在最后一次替换中,这个多余的字符也将被去除
复制代码


【code1】
  1. for %%a in (*《*》*.txt) do (
  2.    for /f "tokens=2 delims=《》" %%b in ("%%a") do echo %%b
  3. )
  4. ::显示txt文件名中《》之间的部分,仍存在跳过以;开头的内容的缺陷,不过这个可以将eol设为文件名中不可能出现的字符来解决
  5. ::比较大的问题是碰到以《为首的文件时会截取错误的部分
复制代码

【code2】
  1. for %%a in (*《*》*.txt) do (
  2.    for /f "tokens=2 delims=《》" %%b in ("@%%a") do echo %%b
  3. )
  4. ::解决方法也很简单,就是在%%a前加上任意不含分隔符的内容,这样无论原文件名是否以《开头,《之前总是有一节。
复制代码

作者: cjiabing    时间: 2011-12-20 23:25

补充2点:
1、要考虑程序的路径、变量、延迟等的设置是否有效?特别是程序在桌面运行时与在没有空格的目录下运行时是有差异的。
2、最好在文章开头解释你所谓的通用性是什么?是批处理程序在大部分支持cmd的机器上都能运行,还是在各种情况下都可以使用?




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