中国DOS联盟论坛

中国DOS联盟

-- 联合DOS 推动DOS 发展DOS --

联盟域名:www.cn-dos.net  论坛域名:www.cn-dos.net/forum
DOS,代表着自由开放与发展,我们努力起来,学习FreeDOS和Linux的自由开放与GNU精神,共同创造和发展美好的自由与GNU GPL世界吧!

游客:  注册 | 登录 | 命令行 | 会员 | 搜索 | 上传 | 帮助 »
中国DOS联盟论坛 » DOS批处理 & 脚本技术(批处理室) » [原创]批处理参数问题一点谈
« [1] [2] [3] »
作者:
标题: [原创]批处理参数问题一点谈 取消高亮 | 上一主题 | 下一主题
无奈何
荣誉版主





积分 1338
发帖 356
注册 2005-7-15
状态 离线
『楼 主』:  [原创]批处理参数问题一点谈

批处理参数问题一点谈
    最近编写了一个批处理程序,想让程序能够灵活的接收两个以下的参数,但在完成过程中几经卡壳,比如怎么解决数量不等的参数个数,怎么实现参数类型的判断。经过一段时间的思考和摸索,总算比较满意的解决了这些问题。接下来我谈谈这个过程,如果你想测试效果的话请在 NT 系统下进行。
    先交待一下这个批处理程序想要接收的参数,一个参数为路径,另一个参数为数字。这样便有了下面的几种组合变换:
1、空
2、路径
3、数字
4、路径 + 数字
5、数字 + 路径
6、路径 + 路径
7、数字 + 数字
前五种情况是程序需要处理的正常的参数组合,后两种是不期望的组合。先看下面一段演示程序,一起来探讨这个过程的处理与实现。
:: demo.cmd  批处理参数处理演示  2000、XP ↑
:: by:无奈何  email:wunaihe@gmail.com  2005.11.17
1│@echo off
2│setlocal
3│set "p1=%~1"
4│set "p2=%~2"
5│set flag_d=0
6│set flag_n=0
7│if not defined p2 (
8│        if not defined p1 (
9│                set "directory=."
10│                ) else (
11│                        set "directory=."
12│                        call :_test "%p1%"
13│                        )
14│) else (
15│        call :_test "%p1%"
16│        call :_test "%p2%"
17│                )
18│if %flag_n% == 2 echo 参数为两个数字 &goto :EOF
19│if %flag_d% == 2 echo 参数为两个目录 &goto :EOF
20│echo 目录为:%directory%        数字为:%number%
21│goto :EOF
22│
23│:_test
24│set "x=%~1"
25│set /a "y=x+1-1"
26│if "%y%" == "%x%" (
27│        set "number=%x%"
28│        set /a flag_n+=1
29│        ) else (
30│                pushd "%x%" 2>nul
31│                if errorlevel 1 set "directory=." &goto :EOF
32│                set "directory=%x%"
33│                set /a flag_d+=1
34│                popd
35│                        )
36│goto :EOF
在前六行中,flag_n 与 flag_d 分别是记录参数中数字和目录个数的两个变量并在以后使用,其余不作过多解释。重点看看第7行到第17行,这是一个 if...else... 分支结构,第一个分支又被分割成为了两部分,p1,p2两个变量分别记录了 demo.cmd 所接收的参数1和参数2,所以整个部分被分成了可以用参数个数描述的,即无参数,一个参数,和两个参数三种情况。分别看看每种分支情况都执行了什么操作。

    先说第9行也就是无参数的情况,语句含义为将变量 directory 赋值为“.”,有必要细说一下这条语句,既然没有任何参数输入到 demo.cmd 为什么还要设置变量 directory 呢?这样做的目的是给 directory 变量设置一个默认值,在以后的调用中如:dir %directory% ;for /r "%directory%" in (*.*) do ....这样类似的命令中即使 demo.cmd 没有接收到路径参数也不会出错,因为有这个默认的“.”,也就是使其在缺省状态下代表当前目录。当然是否确实有必要这样做要看你以后的命令如何使用 directory 这个变量。由于上面的代码只是一个参数接收的演示,也就没有后续的相关操作。如果你不需要对 directory 防空设计,可以将第8-10行替换为 “if defined p1 (” 将其简化,而只保留下一个分支。

    下面谈谈上段提到的下一个分支,也就是第二个 if 语句的 else 部分,即一个参数的情况。因为这一个参数的内容仍然会是路径、数字其中之一,所以还需将变量 directory 赋值为“.”,以防碰到的参数是数字,也就是第11行的功能。再看看第12行,以 p1 为参数跳转到标签 _test ,完成一次类似功能函数的调用。我们不知道完成了什么功能,先放放一放,往下看。下面到了第一个 if 语句的 else 部分,即两个参数的情况。发现分别以 p1 p2 调用了两次 _test 函数。这回我们有必要研究一下 _test 函数到底完成了什么功能。

    直接跳转到第23行,看语句首先将上面调用时发送的参数赋值给变量 x ,接下来执行一次算术操作将值赋给变量 y ,先加一再减一,有些不知所以。再往下看看 if 语句的第一个分支,如果 x 与 y 的值相等,将 x 值赋给变量 number ,并且将 flag_n 加一,我们还记得上文提及 flag_n 是记录参数中数字个数的变量,看来 x 与 y 的值相等,就断定 x 也就是上面调用时传送的参数是一个数字。为什么会这样?第25行应该是关键,在这里有一个小技巧,先插一段 set 帮助:
“在表达式中的任何非数字字符串键作为环境变量名称,这些环境变量名称的值已在使用前转换成数字。如果指定了一个环境变量名称,但未在当前环境中定义,那么值将被定为零。这使您可以使用环境变量值做计算而不用键入那些 % 符号来得到它们的值。”
    现在清楚 set /a "y=x+1-1" 这一句的执行过程了吧! x 被替换为它自身变量值参与运算,当 x 值为数字时先加一再减一其值不变也就是 y=x ;当 x 值为非数字时其值将被定为零,先加一再减一后即 y=0 。所以据此也就可以判断 x 值是否为数字了。细心人会猜想要是 x 本身等于 0 怎么办,这是特殊情况可以在 set /a 句前加以判断,改变程序执行顺序完成指定操作。但是我们这种将变量直接参与数值运算的处理方法也有局限性,比如 x 值 为 0123 会被判断为非数字,这是因为以 0 开头的数字会被解释为 8 进制数字其值为 83 。所以我们可以正确判断的只是自然数字,有方法能回避或者解决吗?我们待会再谈这个问题。

    接下来我们再来看 _test 函数 if 语句的 else 分支,第30行 pushd "%x%" 会保存当前目录,供后续命令 popd 命令使用,并切换到 x 值所表示的目录,简单说就是保存当前目录,并更改目录。下一行根据 pushd 命令的执行情况决定程序的转向,错误的话也就是非目录情况仍然设置 directory 为“.”并退出函数。第32-34行很简单 pushd 执行成功将 directory 设为 x 的值, flag_d 值增一,然后切换到被保存起来的目录。这样便完成了是否是目录的判断。看一下我们发现忽略了非数字非目录的错误输入情况,这只是为了更好的理解这个过程而做的忽略,你可以在开头部分设置一个 flag_o 变量,并在 if errorlevel 1 句增加 set /a flag_o+=1 来记录这种情况。当然为了便于理解和描述我用了并行执行多个命令的连接符“&”;实际中你可以用括号括起多条语句段来分别执行。

    这样我们便实现了数字、目录和其他字符的判断,再回到主程序就好理解了,只是将我们保存的信息显示出来,实际应用中的话再供其他命令使用。想想我们还有什么遗漏情形,比如一个参数 456 是一个目录怎么办,我们可以在第27行前加一个是否为目录的判断?而存在 456 这个目录但本身是我们想要的一个数字怎么办?这是一个没法回答的问题,所以避免这样种种岐义情况最好的办法是要求输入全路径也就是文章开头提到的这个词,而不是我们文章中部一直在使用的目录这个词。我们再来谈谈以零开头的数字的问题,既然要求的是全路径,零开头肯定不是目录,我们用取子字符串命令循环替换掉前面的零再做判断。事实上我们有必要这样做吗?我不敢说没有,那要看你对程序的容错要求程度了。

    回过头来再看看这种参数的处理方式,会发现很难应对多参数的复杂情况,更好的方式应该是 demo /A... /B... /C...这样的接收处理模式,用选项来限定参数。这样的好处是只要按限定符接收就行了,而不用将无顺序的参数交给批处理程序分析判断。这只是初步想法还不知是否能转成可行实用的批处理程序,欢迎朋友们一起来探讨。

补记,本来只是想记录一下碰到的问题来这,没想到罗嗦了那么多。如有纰漏,希望指正。

   此帖被 +18 点积分        点击查看详情   
评分人:【 huanbei 分数: +1  时间:2008-11-6 21:24


2005-11-17 16:42
查看资料  发送邮件  发短消息 网志  OICQ (105400208)  编辑帖子
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 2 楼』:  

Re 无奈何:

      很有见地的一篇主题,根据其讨论的内容和深度,相信可以归入(開發室) ,只是彼处对此能会心一笑的人太少了,还是暂时先放在这里讨论吧。

      动态参数的支持,我在学习批处理之初便曾有接触,只是当时未及深入,疏漏自然难免。后来再编写那个文本遍历程序的命令行增强版(VisitCE)时,曾试图对此进行更深入的探索,但是一入其中,便觉如同幽魂迷宫,错综复杂,需要考虑和斟酌的东西太多了。此时,才对DOS命令行的灵活性有了另一番深入的体会。

      关于多个动态参数的支持,我建议使用 :loop 和 goto loop 的循环对参数分析,这样多少可以避免程序陷入 if else 的迷魂阵中,这也是其他高级语言的代码处理参数的通常做法。对所有的参数都一视同仁,首先判断是否空,其次判断其所属类别,再次判断其是否有效,最后判断其是否可以保存(即是否已经保存或其他情形)。这样即使处理任意多个动态参数,也不需要对代码有太大的更改。

      另外,将参数分为目录和数字的分类法,必然会导致参数的二义性问题,从而导致程序分析的复杂化,许多高级语言规定变量名不允许以数字起始,便基于此项原因(反例是DOS的环境变量)。想要避免它,就需要重新划分参数的类别,你所说的全路径便是一种折中的办法。

      对于判断参数是否数字,如果允许使用外部命令,那么可以考虑 finstr 的正则表达式过滤。

      最后,给出一个题目,大家讨论一下:如何在 MS-DOS下 实现相同的需求?



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2005-11-17 18:31
查看资料  发送邮件  发短消息 网志   编辑帖子
无奈何
荣誉版主





积分 1338
发帖 356
注册 2005-7-15
状态 离线
『第 3 楼』:  

  和之者寡,如我猜想一样这果然是一个淡帖。本想续个下篇完结这个问题的讨论,也算作是学习批处理半年多来的总结,可我实在无力、无心完成了。

  谢谢 willsort 兄的肯定与鼓励,你的建议让我获益颇多。

  上篇文章中留了个尾巴,实在不爽,可我又无心再续。再贴一段批处理程序,算作上篇遗留问题的处理吧。这是我的某个程序的一段,部分更改后做成个演示程序。这段代码是我几次补充修改后的结果,可能有些乱,我不作解释了,因为对此感兴趣的朋友应该都能看明白。
:: demo2.cmd  批处理参数处理演示 2   2000、XP ↑
:: by:无奈何  email:wunaihe@gmail.com  2005.11.25
@echo off
rem xss [/I 输入路径] [/F 显示类型|/V 过滤类型] [/L 输出记录文件] [/O 输出路径]
setlocal
set /a n=0,m=1
set /a I=0,F=0,V=0,L=0,O=0

:loop
set "_temp=%~1"
if "%_temp%" == "" goto :star
if "%m%" == "1" (
        echo "%_temp%" |findstr/i /r "\</I\> \</F\> \</V\> \</L\> \</O\>" 2>nul 1>&2
        if errorlevel 1 echo 非识别参数 “%_temp%” &goto :EOF
)
set /a n=n+1,m=m+1
if /i "%_temp%" == "/I" set /a I=1,F=0,V=0,L=0,O=0,n=1
if /i "%_temp%" == "/F" set /a I=0,F=1,V=0,L=0,O=0,n=1
if /i "%_temp%" == "/V" set /a I=0,F=0,V=1,L=0,O=0,n=1
if /i "%_temp%" == "/L" set /a I=0,F=0,V=0,L=1,O=0,n=1
if /i "%_temp%" == "/O" set /a I=0,F=0,V=0,L=0,O=1,n=1
if "%n%" == "2" (
        if "%I%" == "1" set "directory_i=%_temp%" &set m=1
        if "%F%" == "1" set "filter_f=%_temp%" &set m=1
        if "%V%" == "1" set "filter_v=%_temp%" &set m=1
        if "%L%" == "1" set "log=%_temp%" &set m=1
        if "%O%" == "1" set "directory_o=%_temp%" &set m=1
)
shift
goto loop

:star
echo.directory_i        %directory_i%
echo.filter_f        %filter_f%
echo.filter_v        %filter_v%
echo.log        %log%
echo.directory_o        %directory_o%
goto :EOF
[ Last edited by 无奈何 on 2005-11-27 at 15:02 ]

   此帖被 +4 点积分        点击查看详情   




  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

2005-11-25 23:42
查看资料  发送邮件  发短消息 网志  OICQ (105400208)  编辑帖子
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 4 楼』:  

Re  无奈何:

      知音难觅,古之良训,兄因此感怀可见也是性情中人。

      以下是我的代码,主要针对于 MSDOS/Win9x 环境,在 NT’s 应该也没有什么大问题,当然未经过严格测试,我不能做保证的。

      代码中没有做参数有效性的验证,也没有实现遇到重复开关的验证,不过在实际应用中,可以根据各类型参数的实际情况,比较简单地插入验证代码到相应的模块中。

      兄的代码中,有以下几点疑问:

      1、 set "_temp=%~1" ,我猜测将参数保存至变量的目的在于,剔除参数中的双引号,这是 %~1 的作用,但是我不明白为何将将变量名加参数都用引号括起。

      2、变量 m n,我猜测它们的作用是标示参数的奇偶性,即表明参数是开关还是变量值,但是否可用一个变量的真假来标示?我的方案中因为是用双shift避免了开关和变量值的选择的,这样可能会引起 prog /i /o 这样的识别问题,但是如果在 SwitchI 中加入有效性验证,那么也可以避免。

      3、set /a I=1,F=0,V=0,L=0,O=0,n=1 ,这样的设置会如何识别 prog /i input /o output /i input2 ?
:: ArgParse.bat - Parser of command line arguments
:: Will Sort - 2005-11-26 - WinXP_CMD/MSDOS7.10/MSDOS6.22
@echo off

:Init
for %%e in (directory_i directory_o filter_f filter_v log) do set %%e=

:ParseLoop
if "%1"=="" goto Start
for %%s in (i I f F v V l L o O) do if "%1"=="/%%s" goto Switch%%s
echo Error: Invalid switch '%1'!
goto Quit

:SwitchI
if "%directory_i%"=="" set directory_i=%2
goto NextArg

:SwitchO
if "%directory_o%"=="" set directory_o=%2
goto NextArg

:SwitchF
if "%filter_f%"=="" set filter_f=%2
goto NextArg

:SwitchV
if "%filter_v%"=="" set filter_v=%2
goto NextArg

:SwitchL
if "%log%"=="" set log=%2
goto NextArg

:NextArg
shift
shift
goto ParseLoop

:Start
echo.directory_i        %directory_i%
echo.directory_o        %directory_o%
echo.filter_f           %filter_f%
echo.filter_v           %filter_v%
echo.log                %log%

:Quit
for %%e in (directory_i directory_o filter_f filter_v log) do set %%e=

:end
[ Last edited by willsort on 2005-11-26 at 19:35 ]



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2005-11-26 19:32
查看资料  发送邮件  发短消息 网志   编辑帖子
无奈何
荣誉版主





积分 1338
发帖 356
注册 2005-7-15
状态 离线
『第 5 楼』:  

to: willsort
  高山流水觅知音,能有兄的回复倍感欣喜。

  1、“%~1”如你所说确实是想剔除双引号,如果一个变量的值可能有双引号也可能没有,会造成一些调用的不便。如果一个变量“ABC”值含有空格、分号这样的字符时调用标签函数,call :test %ABC% 势必会将 ABC 拆分为多个参数,所以会这样用 call :test "%ABC%" 这样就会造成传递过去的参数会有双引号包围和两个双引号包围的情况。在我应用中还碰到其他的一些问题,一时想不起来了。我也就养成习惯统一去除双引号了。
  还有用双引号将变量名和值括起来有几点好处,一是这样的话可以使用含有空格的变量名如: set "A B=A-B",二是将变量赋值时防止尾部会有不小心键入的空格如:set "A=" 。这些小技巧可以避免一些不必要的麻烦。

  2、变量 m 与 n 的作用是标示是否是参数标示(开关)和参数变量,但不是以奇偶性来判断的,我最初也是用一个变量采用取余的方法按奇偶判断,出现了你提及的连续出现两个有效参数标示时其后部分全部出错的情况。n 的作用是会确定有效参数标示后紧跟的一个非有效参数标示为参数变量。m 的作用刚好相反,它会认定参数变量其后紧跟的是一个参数标示。

  3、设置 I,F,V,L,O 这几个标志变量的作用就是想让程序能够正确接收无序的并且个数不固定的参数。当一个有效参数标示到来时,对应的标志变量置 1 ,其他标志变量置 0 ;进入下一次循环,当一个有效参数变量到来时,根据标志变量是否为 1 ,就可以判断上次接收到的是哪一个参数标示,然后设置对应的变量值。碰到你提及的有两个重复参数的时候,后一个的值会替代前一次接收的值,也就是以最后输入为准。还有就是当想要标志变量只作开关而无参数变量时,可以直接在最初的判断处添加赋值语句解决这种问题。

  我仔细看了兄的示例,代码确实优秀,流畅程度远远超过了我的拙作。如果再多一层判断完善单步走与双步走的两种分支,也可以很好的解决标志变量只作开关的情况。

[ Last edited by 无奈何 on 2005-11-27 at 13:08 ]



  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

2005-11-26 23:35
查看资料  发送邮件  发短消息 网志  OICQ (105400208)  编辑帖子
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 6 楼』:  

Re 无奈何:

      很抱歉!因为各种主观和客观原因,我的回复被迫推迟了。

      1、兄对 set "_temp=%~1" 的解释确实有理,尤其是防止尾部空格的提示;因为我长期在 MSDOS/Win9x 下编写批处理代码,对带空格参数和带引号参数接触机会不多,所以考虑尚未周全。

      经过测试,发现 ntcmd.set 对命令行中的引号处理很周到,对 set _temp=This is "test string" ! 或者 set "_temp=This is "test string" !" 等情况都能恰当的处理;但是在 MSDOS / Win9x 下就会出现很多问题。另外,无论是在 MSDOS / 9X_COMMAND 下,还是在 XP_CMD 下,set var name=value 的用法都是有效的。

      2、对 m n 的作用我已基本理解,双变量分别标示开关项和非开关项确实是必要的。

      3、起初,我认为你这样的设置会允许开关的重复设定,而这通常是错误的用法,而你在主楼中提到的第6/7组合也被你认定是“不期望的”。不过后来我想到在某些场合中可能会需要这样的用法,这我曾在类 unix 的命令行中和一些复杂的批处理中见到过,所以也就默认了它的存在。

      4、关于我的代码,最初设计这个程序时,我是将 prog /i /o output 和 prog /i input /i input2 都列为错误参数用法的。现在想来, prog /i /o output 的情形还是很常用的,尤其是某些参数只是作为启闭某项功能特性的开关(Switch)时,所以将它按照你所说的单双步分法作了简单的改进。

      此外,我的程序也允许 prog /i input1 /i input2 这种情形,不过与你的代码正相反,它只取第一个设定值;如你所言,想要改成取最后一个也很简单,只需要将判断是否已设置的 if 条件删除即可;而如果要禁止这种情形,也只需要将条件取反后进行错误处理即可。但要处理未必含有设定值的开关时就比较麻烦,需要对参数进行检查了。下面是新的代码,在线完成,未经测试!
:: ArgParse.bat - V2 - Parser of command line arguments
:: Will Sort - 2005-11-30 - WinXP_CMD/MSDOS7.10/MSDOS6.22
@echo off

:Init
for %%e in (directory_i directory_o filter_f filter_v log) do set %%e=

:ParseLoop
if "%1"=="" goto Start
for %%s in (l L i I o O f F v V) do if "%1"=="/%%s" goto Switch%%s
echo Error: Invalid switch '%1'!
goto Quit

:: 一个有设定值的开关,如果重复设定将取最后一个
:SwitchI
set directory_i=%2
goto Next2Arg

:: 一个有设定值的开关,如果重复设定将取第一个
:SwitchO
if "%directory_o%"=="" set directory_o=%2
goto Next2Arg

:: 一个有设定值的开关,如果重复设定将抛出错误后终止程序
:SwitchF
if not "%filter_f%"=="" echo Error: Replicative switch '%1'!
if not "%filter_f%"=="" goto Quit
set filter_f=%2
goto Next2Arg

:: 一个可能有设定值的开关,如果未在其后设定值,将取默认值
:SwitchV
set filter_v=default
for %%s in (l L i I o O f F v V) do if "%2"=="/%%s" goto NextArg
if not "%2"=="" set filter_v=%2
goto Next2Arg

:: 一个没有设定值的开关,只有启闭功能,重复设定将反复取反
:SwitchL
if "%log%"=="" set _log=on
if "%log%"=="on" set _log=off
if "%log%"=="off" set _log=on
set log=%_log%
set _log=
goto NextArg

:Next2Arg
shift
:NextArg
shift
goto ParseLoop

:Start
echo.directory_i        %directory_i%
echo.directory_o        %directory_o%
echo.filter_f           %filter_f%
echo.filter_v           %filter_v%
echo.log                %log%

:Quit
for %%e in (directory_i directory_o filter_f filter_v log) do set %%e=

:end
[ Last edited by willsort on 2005-11-30 at 12:24 ]



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2005-11-29 17:34
查看资料  发送邮件  发短消息 网志   编辑帖子
无奈何
荣誉版主





积分 1338
发帖 356
注册 2005-7-15
状态 离线
『第 7 楼』:  

to:willsort
  事实上 prog /i input1 /i input2  这种情况取前者与后者都是合理的,只是策略问题,完全可以怎么方便怎么来。
  兄的下面一段代码,按你的功能提示来看好像漏掉了一种可能情况。

  Quote:
:SwitchV
for %%s in (l L i I o O f F v V) do if "%2"=="/%%s" set filter_v=default
for %%s in (l L i I o O f F v V) do if "%2"=="/%%s" goto NextArg
set filter_v=%2
goto Next2Arg

测试:prog /i input1 /v 发现并未按设想的赋值。可以加一条语句如下:
:SwitchV
for %%s in (l L i I o O f F v V) do if "%2"=="/%%s" set filter_v=default
for %%s in (l L i I o O f F v V) do if "%2"=="/%%s" goto NextArg
set filter_v=%2
if "%2"=="" set filter_v=default
goto Next2Arg
  还有一个疑问,相同条件的语句兄为什么不作合并。如:
for %%s in (l L i I o O f F v V) do (
        if "%2"=="/%%s" set filter_v=default
        if "%2"=="/%%s" goto NextArg
)
这样可以减少一次循环,或者更简洁的将 if 句也合并,是兼容性的考虑吗?我不了解 DOS 下的问题。



  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

2005-11-29 21:21
查看资料  发送邮件  发短消息 网志  OICQ (105400208)  编辑帖子
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 8 楼』:  

Re 无奈何:

      1、prog /i input1 /v 确实是个问题,你的修改是必要的;而且真正要应用的时候,还需要防止 /x /y 或其他无效的开关情形,此时进行有效性验证就是必须的了。

      2、两句同样的 for + if 确实是出于兼容性考虑,在 MSDOS / Windows 下,是不支持语句块的。虽然通过特殊的方法可以使两句合并,但是这里并不采用,一方面是兼容性的考虑,另一方面是可阅读性的考虑。

      3、prog /i input1 /i input2  这种情况,取前者与后者适合于不同的应用场合。

      比如在某些场合,我们可能会使用变量来保存带参数的命令行,然后在以后的某个环境下引用它,此时我们可能需要改变某个开关或参数,却出于某些原因无法修改变量,此时就需要取后者的策略,这样我们可以在引用变量的后面加上新的开关或参数来改变程序的运行状态。

      至于取前者的策略则比较多见,但一般没有特别的目的性。但有一重特殊的情况是与上面正相反,我们可能会使用变量保存命令行的部分参数,然后在以后的某个环境下引用它,此时我们可能需要固定某个开关或参数,却出于某些原因无法修改变量,此时需要取前者的策略。或者某些程序会以各种形式预置一些的常用的命令行用法,而且不欲用户有意或无意的修改这些用法,则也需要取前者的策略。这类似于某些 unix 类程序中的 -- 命令行终止参数。

      另外,刚注意到你的新签名,确实富有创意和技巧,只是文辞似乎略显伤感了些,恐怕会给论坛的新人带来负面的影响吧。玩笑而已

[ Last edited by willsort on 2005-11-29 at 22:26 ]



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2005-11-29 22:19
查看资料  发送邮件  发短消息 网志   编辑帖子
无奈何
荣誉版主





积分 1338
发帖 356
注册 2005-7-15
状态 离线
『第 9 楼』:  

哈哈,以后就用你的这个构架了,给个授权吧!

我的签名确实花了一些心力,语句我尽量的精简,想让其保持功能的前提下拥有最少字符,这是我目前能做到的最好情况(%ComSpec% 替换为 cmd 不算),当然也就没有了可读性,故弄玄虚增加点神秘感。再者,无奈何不是一种持久的人生态度也不是现状的反映,可以理解为对种种不能为不可为之事的解嘲、劝抚,或于己事或于人事,多一些自抚调整少一些空劳抱怨。映于己映于人,也有太多的体现。伤感是肯定的,也显低调,但希望的不是低沉。我最初的词句是终是无可奈何,发觉不是我的本意,悄悄改了一字。



  ☆开始\运行 (WIN+R)☆
%ComSpec% /cset,=何奈无── 。何奈可无是原,事奈无做人奈无&for,/l,%i,in,(22,-1,0)do,@call,set/p= %,:~%i,1%<nul&ping/n 1 127.1>nul

2005-11-30 00:19
查看资料  发送邮件  发短消息 网志  OICQ (105400208)  编辑帖子
willsort
元老会员

Batchinger


积分 4432
发帖 1512
注册 2002-10-18
状态 离线
『第 10 楼』:  

Re 无奈何:

      我的代码既没有声明 Copyright ,也没有附加任何 License ,所以也就不存在授权的问题,你当然可以自由的使用它。对网络自由共享的精神我是很欣赏的。

      但是,一个好的框架或代码是需要经过反复测试和不断改进后才能正式应用的,而我的这个代码只是在线编写的一段代码,很可能存在许多潜在的问题和不完善。

      昨夜入眠之前,就突然醒起一个地方可再做一下改进,就是你提到的双 for 语句处,我将前一个 for 省略了。代码不再重贴,只是编辑了6楼的原 V2 版代码。



※ Batchinger 致 Bat Fans:请访问 [讨论]批处理编程的异类 ,欢迎交流与共享批处理编程心得!
2005-11-30 10:35
查看资料  发送邮件  发短消息 网志   编辑帖子
maya0su
中级用户




积分 241
发帖 131
注册 2005-9-28
状态 离线
『第 11 楼』:  

苦者律己,行者无奈……
人生本就是一件痛苦的事,可是生来为人,我们不能沉沦,只有振作,吾爱吾爱之人……奈何花凋零……
无奈何兄的贴子我仔细反复看了看,最终的结果是我不参与讨论,因为我是今天才发现的这个帖子……而我的能力也非常有限,对于你提出的问题只能再去研究……而willsort兄的回贴确实精彩,你们在问与答之间完成了最初所设想,可喜可贺……弟我只能替你们高兴!
网络的最初设想就是自由和共享,可是现在网络成了人圈钱的工具,实在让我辈心寒,本着自由和共享的精神我谨希望以我们的微薄之力来延续这重种共享和自由,无奈何兄的签名我测了测,很有意思!
试出一个题目:能不能写个批处理程序,用一个字一个字的显示方式,显示出一段话呢?而且是批处理,双击后在窗口显示这短话,完成后屏幕暂停!
仅是想和兄们做个游戏,关注不关注无所谓……博君一笑而!



房东说:这娃是个好孩子!
2006-1-16 23:43
查看资料  发送邮件  发短消息 网志  OICQ (55115315)  编辑帖子
mrhjzhang
初级用户





积分 100
发帖 39
注册 2005-10-27
状态 离线
『第 12 楼』:  

路过,纯支持

2006-1-19 16:45
查看资料  发短消息 网志   编辑帖子
220110
荣誉版主




积分 718
发帖 313
注册 2005-9-26
状态 离线
『第 13 楼』:  



  Quote:
试出一个题目:能不能写个批处理程序,用一个字一个字的显示方式,显示出一段话呢?而且是批处理,双击后在窗口显示这短话,完成后屏幕暂停!

Re maya0su:
参见无奈何的个人签名。
但其代码真让人晕。呵
希望无奈何朋友能整理出一个易看点的格式。

[ Last edited by 220110 on 2006-2-4 at 16:54 ]

2006-2-2 10:26
查看资料  发送邮件  发短消息 网志   编辑帖子
zah98
新手上路





积分 9
发帖 4
注册 2006-10-22
状态 离线
『第 14 楼』:  

支持一下,有点看不懂

2006-10-22 11:40
查看资料  发送邮件  发短消息 网志   编辑帖子
gxfc
新手上路





积分 17
发帖 11
注册 2006-10-22
状态 离线
『第 15 楼』:  

好帖,值得研究

2006-10-22 13:27
查看资料  发短消息 网志   编辑帖子
« [1] [2] [3] »
请注意:您目前尚未注册或登录,请您注册登录以使用论坛的各项功能,例如发表和回复帖子等。


可打印版本 | 推荐给朋友 | 订阅主题 | 收藏主题



论坛跳转: