[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[其他] 批处理之我见

本帖最后由 leeonix 于 2011-10-19 20:42 编辑

By LeeoNix 2011年10月19日

2011年10月8日,C语言的作者。Dennis Ritchie去世了。看着这个消息我发呆了很久。可以说,你看我这篇文章的时候,面前所有的“虚拟”的东西,都与这位大师有关。他是真正的大师,那天我决定写1000行C或者其他的代码。那天我写了大概500行的C代码,写了一个生成批处理的Python脚本。纪念这位大师,作为一个程序员,除了写更精细的代码,没有别方式去纪念他。

和朋友聊天,他说,既然你用到了Python,就全用就是了。干吗还要生成批处理呢?我的回答,批处理的环境变量依赖是很方便的,而且我还要用vc编译3个vc工程,一个Delphi工程。还要用sed处理合适的文本输出。用Python组合这些操作就非常麻烦了。

写完这些之后,我就想写一篇文章,以前,一个后辈说从这里学了不少东西,今天我就注册个号发一篇文章回馈一下。其目的是,批处理该用什么,以及什么时候该用到批处理。

1、批处理的定位。

所谓的Windows批处理。实际上是CLI(command-line interface,命令行界面)的一种,具体见(http://baike.baidu.com/view/160512.htm)。而CLI区别与用户图形界面,其优势是,可以根据各种命令组装成批量执行的命令。
批处理其优势就是Windows提供的原生工具。这一点优势就足够说明为什么在Windows下使用批处理,多的优势根本不用多说。其欠缺的也很明显,缺乏模块化的语句,缺乏对数字和逻辑类型操作的方法,条件分支和循环语句都很弱小,字符串操作也很弱。

批处理依赖的环境是一个开放式的大环境,面向整个系统。换句话说是其实是“不安全”的,比如我用call默认调用另外一个批处理,实际上你可以在主题批处理上用到被call的批处理里面的变量名。打个不恰当的比方说,就像一个大厂房,倘若你和你的异性伴侣在OOXX,实际上路过想看的人都是可以看得到的。虽然是可以用setlocal...但其优势又是因为是开放式的,而且可以根据环境变量去获取,各种东西随便用,在轻量级调用方面,就省却了很多麻烦。

如果有工厂经验的人,会理解我说的话。其实批处理最好的定位,就是一个大的方便的组装车间。而不要特别去想成为加工车间。强求只会陷入误区。

2、关键的操作符。
Unix最初的创建者中,有位大师叫Doug MclIroy。他低调的隐藏在Ken Thompson和Dennis Ritchie之下。并不为所有程序员所知。他为Unix发明了管道以及使用管道操作符"|",而这点被借鉴到了Windows系统。

看到这里,请记住管道以及管道的发明者,Doug MclIroy。

管道的意义非常简单:上一个指令的输出作为下一个指令的输入。搜索管道的介绍,你会看到管道的基本指令。ls -l | more。而在Windows下,其实这个也是很有意义的指令。比如C:\Windows\System32这个文件夹下,有非常非常多的文件。一次是看不完的,那就输入C:\WINDOWS\system32>dir | more。dir显示不全的交给more显示就可以了。

举个我实际的例子,我写的Lua脚本,有个debug库,我为了提高效率,在给别人的时候会把这个有关debug的信息处理掉。只要利用sed把根据关键字注释掉,然后扔给lua编译器便以为byte code就可了。listfile是我预先写好的或者用>操作符生成的临时文件。
代码:
for /f %%i in (%listfile%) do (
    sed.exe "s/debugstr\./--/g" %%i | luac.exe -o %TEMP%\script\%%i -s -
)

有关管道的介绍,可以从网上找到很多。

输入操作符,输出操作符。< > << >>这也是借鉴的Unix系统的操作符。只能用于标准输入输出进行操作。而例如stderr输出的,则不会被使用。具体在下面会有例子。

3、命令行工具。
使用批处理,就与命令行工具息息相关。而cmd.exe本身提供的指令非常有限,参数也很有限。所以命令行工具是主要补充。其实Windows本身提供的命令行工具,打开C:\WINDOWS\system32,会看到很多普通图标的工具,也可以从网上查到大概的功能。但很多提供的功能很有限用起来也比较无奈,比如findstr,还不如下载一个grep用。而自己用编译类语言写的工具,或者用脚本语言写的,只要符合标准输入输出流的,都可以作为工具集使用。

Unix工具的易用性是毋庸置疑的,在Windows上使用,好几个实现版本。

gow这个是比较全也比较轻量的,是整理的gnu工程再发布的。
http://wiki.github.com/bmatzelle/gow/
gnuwin32是gnu官方提供的,文档比较全。更新比较方便,但很多可能你不需要的东西在里面。
http://gnuwin32.sourceforge.net/
UnxUtils也是一个整理的工具集。
http://sourceforge.net/projects/unxutils/

个人推荐gow。

使用unix工具集,会有几个选择。面临很多的选择,dir还是ls?findstr还是grep?del还是rm?copy还是cp?就速度上,Windows提供的当然快很多,但作为使用管道的工具来说,还是后面的工具更合适。

但是很多冲突需要注意,举个例子:find命令,被windows定位为搜索字符串,但在Unix工具里面是搜索文件的,而find命令搜索文件,是很方便的,结合xargs可以作很多事情。类似的冲突还是比较多的。而gnu提供的find命令是很好用的。扔掉windows带的那个find.exe,从C:\Windows\System32下可以安心删除它。换成grep。

4、正则表达式。
文字处理方面,正则表达式是必须的,但在批处理上用大多数的正则表达式是无意义的。
Unix最初的创建者中,还有有位大师叫Brain Kernighan。他在《程序设计实践》里介绍了一个极简单的grep实现代码。只提供了四个操作符"." "*" "^" "$",这四个字符,体现了一个好的“记法”可以增长人的工作效率。在书里面提到了,就这四个操作符就可随意解决大部分问题。而另一本书《代码之美》的第一篇也是对这个实现的一个介绍。《程序设计实践》里,大师说了:好的记法只有与人们的工程经验相结合,才能产生自然而有效的工具。

而为什么要使用这些字符?接触批处理的,都会有一个概念,叫“通配符”。比如dir *.dll这样的。*代表了“所有”。而*号,就是dir这个工具提供的“记法”,让用户明白“所有”这个概念。仅仅使用dir这样的工具提供的是远远不够的。所以才要使用正则表达式。在批处理里面使用简单的正则表达式足够,如上面提到的4个。而利用grep这样的工具过滤,会更容易让人理解。而上面的dir *.dll也可以用dir | grep "\.dll$"来做到同样的功能,但过滤了很多无用的信息方便下一步操作。

进一步的例子:dir | grep "\.dll$" | awk "{ print $1, $3 }" 会输出列表内dll文件的日期和大小。
利用正则表达式可以让你找到你想要的。

5、纯文本。

Eric Raymond,在《Unix编程艺术》里,多次提到了纯文本的威力。缺乏数据结构支持的批处理利用 < > << >> 输出流生成中间文件,再经过处理之后,就成为下一个需要用的参数。也可以生成一些配置文件,作为其他工具使用的参数来处理。如果批处理的功能遇到问题,也可以通过模板,利用输入输出流生成一个临时批处理来操作。不要太信任二进制文件,但一定完全信任纯文本。
比如获取文件名,用dir /b > list.txt生成一个list文件,然后用for /f %%i in (list.txt) do echo copy /y %%i %TEMP%\%%i.bak类似这样的循环操作,操作完del list.txt,这就成为一个备份文件的好例子。

dir /b > list.txt
for /f %%i in (list.txt) do echo copy /y %%i %TEMP%\%%i.bak
del list.txt

再举个例子,我写了个工具,是一个命令行打包的工具。但支持的参数类似这样的格式:
#-------------------
#(路径) (类型)
%TEMP%\script script
D:\Work\images bmp

然后打包成一个我需要的文件。我通过使用%cd%获取当前目录,然后获取合适的路径再调用我自己写的打包工具。
echo %TEMP%\script script > pack.txt
echo %cd%\images bmp >> pack.txt
packer pack.txt
del pack.txt
这样一个简单的批处理,就让我的工具做到与环境无关的通用性了。而且参数可以通过生成这个配置文件可编辑。

6、脚本语言。

现在脚本语言越来越多了。awk,perl,python,lua,ruby,javascript,甚至java和C#都可以参与进来。
为什么要用到脚本语言。就是为了作为批处理功能的补充。我在第一条说过,批处理的定位是组装车间,不是加工车间,而加工车间,交给脚本语言。
学一种甚至几种脚本语言是非常有必要的。
虽然上面我用了awk,但awk并不完全推荐,局部简单的还可以,其功能完全可以被perl替代。awk的速度优势,在现在的计算机速度下,已经可以忽略。
而我常用的单行命令基本可以用perl替代,而非单行的脚本可以用python也可以用lua来写。
为什么要用到脚本语言:
    a.批处理对于字符串的处理是很弱的。缺乏更好的替换,缺乏类似printf这样的格式化输出,更缺乏整个Template替换。但写一个简单的perl脚本或者python脚本就完全弥补。
    b.批处理缺乏数值计算的能力。有的地方日期和数值比对是很重要的。
    c.批处理缺乏合理的数据结构,数组,key-value的表格。而针对字符串生成数据结构的split和join的字符串处理。

顺便说一下个人的喜好问题,我是强烈的反感带“VB"两个字母的东东的,比如VBScript我是绝对不用的。

最后,没什么可说的了。
提醒一下,关于字符串以及文本的处理,可以说,你能想到的,20多年前美国玩操作系统的那些老家伙都想到了,你没想到的,那些老家伙也想到了。利用管道很多都可以做到。
引用荀子的一句话:吾尝终日而思矣,不如须臾之所学也。
2

评分人数

    • vsbat: 难得有前辈出来技术 + 1
    • cjiabing: 专业,中肯,敬佩~技术 + 10

这个不同的目地可以学不同的语言的,比如只想自己写一点小程序自己玩的学vb就足矣,而对编程有特别爱好的就可以学习c然后深造了!

TOP

呵呵,来个玩笑贴,我想用C语言制作一个原子弹,去解放“美国”。我也是在网吧学的,不要因为别人的认知来改变你的行为,如果这样的话,你为什么不能看看比尔.盖次呢!
枫中残雪:风停了,我的心却在动,让我心中的寒意走向远方

TOP

回复 35# zaixinxiangnian


    说实话这个真的是因人而异的。能不能有个好的习惯和思维主要因素还是看个人的。楼主觉得VB不好,对他没有帮助,是对他个人来说的,所说的话也只是仅供参考。你也不必太在意,坚持好自己的本意,不要因为一两句话就三心两意了,这个可是学习的大忌。网上很多说法,比如这个语言好,那个语言不好,你随便搜索“XXX语言怎么样?”,每个人的说法都会不一样。所以我觉得,坚持自己的本意,只要认真去钻研,够刻苦,成为一个编程高手也是迟早的事情。个人看法:编程,不是单单会点语法就可以的,更讲究一个“思想”和“境界”。“思想”就是如楼主所说的一们编程语言的精髓,VB也有自己的精髓所在。“境界”就是程序员的层次深度,如果你学习的是Windows编程(VB就是),这个"层次"更重要的是看你对Windows了解多少。如果你对Windows从底层到外壳都有很高的认识,那么,无论用什么语言写很难的程序都会绰绰有余。当然了,每个语言都是有个自己的特点的,比如C更贴近底层,VB贴近外壳编程。如果有时间,你也是可以多学几门语言的,这样你就可以知道哪门语言更加适合自己,而且也有触类旁通的效果,充分利用每门语言的特点,取长补短,相辅相成。我还是坚持那句话:语言是死的,人是活的。这句话你应该懂吧?
---学无止境---

TOP

回复 35# zaixinxiangnian


亲,你见过世界上有哪门技术是所有的人都说好的吗?
别人随便说上几句话,你就准备放弃学习一门技术。还有啥好指点的啊

TOP

回复 27# leeonix


    怎么不上线了。。。各位版主能给指点下吗?

TOP

本帖最后由 zaixinxiangnian 于 2011-10-25 21:42 编辑

回复 27# leeonix


    我对哥们的话很在意,因为我刚买了一本VB6.0从入门到精通(第二版) 哪天去新华书店看没有了。生怕它没有了赶快在网上买了一本。打算把批处理和网络的一些知识(因为我是在网吧,也想提高自己吗)学了,然后开始全面进行学习VB。反正就是开始学习编程。但看到你说的会给一个程序员带来一个坏的习惯。我就有点后怕了。习惯是个很强大的东西。所以希望你和在座的批高手们给指导下-引下路。  QQ:657614933

TOP

stderr 也很好用啊,我就写过一个 小程序,用来读取一个EXCEL表,然后进行分析,最后通过stdout输出经过整理的csv文件,通过stderr输出统计数据文件。

TOP

尺有所短,寸有所长,各尽其能,综合应用,先解决问题,再考虑其他。。
sxw 发表于 2011-10-19 20:27



    赞个!
    哀悼一分钟....

TOP

存在说明它合理,没有一种语言不是在学习别的语言,相互学习,相互影响,批处理别无它长,它专业,偏执

TOP

为什么拿这最普通的脚本与那些专业的语音比呢。。。。

TOP

看了开头,觉得还好,但后面觉得真糊涂了!~
批处理嘛,学了才知道怎么样,不要轻易和其他语言比较,一比他就阳痿了。
不过能用就行,用一个记事本就能解决的问题何必去找一个平台再装一些软件再写?
简单实用高效乃精髓,不要离开这个谈批处理。
寂寞是黑白的,但黑白不是寂寞,是永恒。BAT 需要的不是可能,而是智慧。

TOP

扔盆凉水:批处理就是命令的合集,是对重复命令的操作解放,所以我的思维明显和各位不同,因为是命令合集,所以拿它和C,B之类放在一起讨论不太合适……
1

评分人数

    • powerbat: 正是我想说的。竟然有人将批处理与“语言” ...技术 + 1

TOP

>>倘若我需要生成一个list.txt的时候,会通过其他方式再处理一次这个list.txt。然后再用for去做。
>>不是很懂,不知道为什么要拐这么多弯。
我不知道为什么纠结与这个简单的例子,我知识举个生成纯文本使用的例子而已。没别的,有两点优势,
第一,组织自己的结构。
第二,保存一个文件,如果出错就可以看到这个list.txt到底错在哪里,类似一个日志。所以我宁愿生成个文件,也不会写类似for /f in ('dir /b | grep "*\.*"') do这样的。而且后面的删除给别人前都是被注释保留的。

>>grep给你的功能是过滤。多数的管道操作就是由grep处理然后再交给sed。而不是在awk里面写判断。
>>不错,grep是过滤,但是sed/awk本身可以过滤啊,不用你自己写判断呀。干嘛又是grep又是管道呢?说到呼吁什么东西代替它,别逗了,不在一个层面。

我当然知道类似awk在后面是可以用~=加条件过滤是不是显示前面的条件,sed也是可以的。但经常使用grep的人都习惯使用grep,因为日常的工作,操作grep远远多过sed和awk。结合grep和管道做事,这也是我说的习惯的问题。我用vim写代码,使用各类shell,一天要输入grep至少60次以上,像vim自己就有查找vimgrep,为什么vim自己还加了调用外部grep的接口?无它就是习惯而已。

>>然后现在不知道有多少人在骂谭老头
>>确实有很多人在骂。我感脚吧,这面不少人是看了几本外文C教材就觉得自己有两把刷子的。而那些低调的高手们给出的评价往往显得谦逊:人家谭老师毕竟让那么多中国人迈进了C门槛。
我和你的观点是一样的,而且我不是骂老谭的那群人的一员。在80年代,那么封闭的年代,连县城的书店都不一定买得到道德经的时代,没有互联网的时代,老谭的书让人知道了BASIC和C语言。是一代人的领路人。但后面随着新的书籍的进入,老谭还用他的书和教学,就是在误人子弟,那就真的找挨骂了。像类似高校的,比如邱钟潘的“教授”,还有臭名昭著的清华大学出版社。你可以搜索一下有多少人骂。我只是老谭的反例,阐述一个坏习惯的问题。坏习惯养成了想改都很难改。

>>对了,是没有替换命令。但是用Python完全可以做到
>>有哪种语言或者脚本做不到吗?
当然有,他叫做“批处理”或者叫Batch,批处理本质上就是一种“脚本语言”。还有某些小语言,还有某些叫做语言的。比如XML,HTML。XML也是一种叫做“语言”的东西。

TOP

倘若我需要生成一个list.txt的时候,会通过其他方式再处理一次这个list.txt。然后再用for去做。

不是很懂,不知道为什么要拐这么多弯。

grep给你的功能是过滤。多数的管道操作就是由grep处理然后再交给sed。而不是在awk里面写判断。

不错,grep是过滤,但是sed/awk本身可以过滤啊,不用你自己写判断呀。干嘛又是grep又是管道呢?说到呼吁什么东西代替它,别逗了,不在一个层面。

我并没有看到批处理有这四个操作符"."(所有字符) "*"(0个或多个) "^"(行首) "$"(行尾)

如果你认为没有,那就没有吧。我也不知道是不是因为你干的少。

然后现在不知道有多少人在骂谭老头

确实有很多人在骂。我感脚吧,这面不少人是看了几本外文C教材就觉得自己有两把刷子的。而那些低调的高手们给出的评价往往显得谦逊:人家谭老师毕竟让那么多中国人迈进了C门槛。

对了,是没有替换命令。但是用Python完全可以做到

有哪种语言或者脚本做不到吗?
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

返回列表