Board logo

标题: [其他] 【共同参与】让cmd解释表达式语言 [打印本页]

作者: plp626    时间: 2009-5-29 20:18     标题: 【共同参与】让cmd解释表达式语言

今天发了两个帖子解决了问题,很感谢论坛的会员们
接着
突发奇想,再继续发散思维下特有如下想法,想让cmd人性化点

大家都知道脚本中可以用call方法调用子过程,但是这种方法很麻烦
要人为设定返回变量,然后再用,习惯了高级语言后对此种调用发法很不爽,还有cmd不支持浮点运算,数学函数自然不能用,(论坛里有个math.exe,就很好大家可以搜索关键字math,正式这个math.exe让我产生此想法)

提议写个解释器(命名expr),把子过程的call方法封装 对子过程的调用用高级语言的 varable=fun(arg1,arg2,,,) 形式,对于有返回值的函数用等号去接受,(这一点p可以说是得天独厚,是大多数语言无法比拟的,因为它没有变量类型)
expr   var=fun1(arg1, arg2, ... fun2(p1, p2, ...)) ; var2=fun3(...) ; fun4(....);

现在想到一个问题就是如果expr作为三方工具,那么var的值只在expr的生存期有效,当expr将控制权返回给cmd时,用
return var;
却要求为int型,而且cmd能接受的只有errorlevel变量,看来要做不只有这些了
若再换一种思路,不return var; 而是printf("%s", var); 然后再写个bat脚本for /f
去抓取信息,
于是产生用纯批处理写expr的想法,但是效率可想而知,
于是还是回到用 c语言+bat的for /f的思路

若真是喜欢cmd(linux的强大正是有众多的fans一点一滴地积累而成)愿意给它做点东西,开始吧

有兴趣来此贴讨论:
expr编写的可行性研究

[ 本帖最后由 plp626 于 2009-5-31 21:11 编辑 ]
作者: 随风    时间: 2009-5-29 20:47

说实话不太懂楼主的意思
用call方法调用子过程,但是这种方法很麻烦,要人为设定返回变量,然后再用。
什么情况下是楼主所说的 人为设定返回变量呢?
call :loop var
echo %var%
pause
:loop
rem 省略
goto :EOF
以上,变量var 就是人为设定的返回变量吗?
作者: plp626    时间: 2009-5-29 21:07

原帖由 随风 于 2009-5-29 20:47 发表
说实话不太懂楼主的意思
用call方法调用子过程,但是这种方法很麻烦,要人为设定返回变量,然后再用。
什么情况下是楼主所说的 人为设定返回变量呢?
call :loop var
echo %var%
pause
:loop
rem 省略
goto  ...

恩就是,也许你体会不深,
我给你举个通俗的例子,
现在有个两子过程:fun <int> <int> [ret]    可以返回两个整数的和,
:fun2 <int> [ret]                                      可以判断这个和是不是素数,是素数返回1 不是返回0
我现在有数1 数2,想知道它们的和是不是素数
你调用的基本形式是
   1.   call :fun 数1 数2 和
   2.   call :fun2  和  ret

现在用这样的形式表示
expr ret=fun2(fun(数1,数2))
多方便,如果再优化,给expr加运算符性能,这样使用
expr ret=fun2(shu1+shu2)
多方便,简洁(其实本来就应该这样,这是ms没有给cmd这些功能)
作者: plp626    时间: 2009-5-29 21:10

我们现在的call 方法形式上接近于汇编call 方法
所以我们才不能把批处理的子过程叫做子函数

想一想高级语言的函数是怎么被调用的,就有体会了
作者: 随风    时间: 2009-5-29 21:19

不懂高级语言,但看你的例子
“如果再优化,给expr加运算符性能” 这应该是子程序的编写问题,应该不在此帖讨论范围内。
那么区别是
现在的调用方法:call :fun 数1 数2 ret
你说的调用方法:expr ret=fun2(fun(数1,数2))
其结果都是 %ret% 的值等于 数1+数2
如果是这样的话,我不觉得这个 expr 有什么更方便的地方啊?
作者: defanive    时间: 2009-5-29 21:20

这样东东我貌似做过类似的,那个vbs作为新一代第三方的研究
http://bbs.bathome.net/thread-3426-1-1.html
虽然跟这个有点差别,但是基本雏形都出来了,但是效果实在不行
可以参考一下R×的函数库,用起来还是非常顺手的,不会觉得麻烦

cmd想要真正实现高级语言的功能还是有很大麻烦的,至少连VC++做这些都麻烦
程序所产生的改变在结束后基本还原
开发新的解释器吧,以cmd为内核,新的执行机制可能要好很多
之前开发GUI版cmd的时候也遇到了很大问题

总之,cmd相关的开发还有非常多,例如多线程批处理也在开发中,还有上述所提的GUI版cmd
但是很多项目都搁浅了,人手不够是一个原因,二也是cmd和控制台本身的缺陷

想要得到实质性的进展还要好久的啊
作者: plp626    时间: 2009-5-29 21:20

我用c写了个命令行的 数学函数中缀表达式计算工具 好费力,优化了N此,结果再cn-dos无意间发现了这种东西早就有了(math.exe)
http://www.cn-dos.net/forum/view ... &highlight=math

如果要写expr我想和math的方法差不多,要做词法分析,不只是看数据结构了,编译原理少不了了,但是有个思路还是没通,让expr中的返回值很合理地再cmd中也有效,因为要让expr支持很多函数在一行使用(用;隔开) 这个实现起来并不是我1楼的那么简单

广泛听取大家想法
作者: defanive    时间: 2009-5-29 21:27     标题: 回复 5楼 的帖子

上述这个写法对程序的可读性有了极大的提高,也初步实现了返回值的效果
高级语言之所以效率高,原因是有函数返回值
a=len("Hello")*2
首先将执行len("Hello"),将返回值5代入执行a=5*2
而批处理的机制则需要
call :len "Hello" a
set /a a*=2

我还之前还提倡批处理库文件的编写,实际上这是个很有意义的项目
高级语言,其内置的函数、关键字、语句不过几十种,跟批处理相当,然而其拓展功能非常多
每一个包含拓展功能的文件,程序加入以后繁杂的拓展功能函数就不用重复编写了
例如VC++,其拥有的头文件数目可能把所有批处理第三方加起来都无法比拟
作者: defanive    时间: 2009-5-29 21:31     标题: 回复 7楼 的帖子

在cmd中有效获取,目前不能直接写入变量。原因是system函数每次运行都会启动一个新的command来执行内容,结束后销毁。
现在的解决方案只有你说的输出(文件或其他设备)+for /f读入
写新的解释器好点吧,可以实现数据类型、Class、函数返回等,尽管难度极高
作者: plp626    时间: 2009-5-29 21:39

原帖由 defanive 于 2009-5-29 21:20 发表
这样东东我貌似做过类似的,那个vbs作为新一代第三方的研究
http://bbs.bathome.net/thread-3426-1-1.html
虽然跟这个有点差别,但是基本雏形都出来了,但是效果实在不行
可以参考一下R×的函数库,用起来还是非常 ...

看了你的那帖子,我们有共同的"不爽"
不过你的思路
创建VBS —> VBS计算结果 —> VBS返回结果 —> 通过For获取结果 —> 删除VBS
最后这个删除VBS可以省略
我之前最先想的也就是VBS, 只是想到他的返回是个"对话框",于是想到把它作为底层文件,
再写个expr.bat(for /f + cscript)去调用,而和用户直接接触的是这个expr.bat
而用户在调用时候是 call expr ...... 多了个 call 还不爽,
对于 处理表达式 数据结构有类似的算法,甚至代码,干脆写个expr.exe, 以后求做数学计算的感觉就好像set/a的感觉直接,做字符串操作也是如此,省去了一大片临时变量。。。。
作者: defanive    时间: 2009-5-29 21:45

数学计算的话一般还是2个问题,括号匹配和运算结束值处理
括号匹配还是有一定难度的,网上已有相关代码
结束值处理,一个是返回errorlevel只能是int,二个是程序结束则局部变量销毁的问题
结束值处理的两个问题是关键

[ 本帖最后由 defanive 于 2009-5-29 21:46 编辑 ]
作者: defanive    时间: 2009-5-29 21:57     标题: 纯P基本功能

比较简单的代码,可以作为另一个bat使用,也可以作为函数来使用

Expr.bat
  1. @mshta vbscript:createobject("scripting.filesystemobject").opentextfile("%temp%\_tmp",2,True).write(Eval(%2))(window.close)
  2. @set /p %1=<"%temp%\_tmp"
复制代码



使用时:Call Expr a "1+2"
1+2的结果保存在变量a中
作者: defanive    时间: 2009-5-29 22:01

除了运行的时候窗口会闪一下,效率有点低以外,貌似都没有什么大问题了

mshta使用vbs只能执行一行代码,所以有时候实现起来很困难
作者: plp626    时间: 2009-5-29 22:10

可以不生成临时文件,数学计算需要将字符类型转换为浮点型,或整型什么的
vbs有像C的atof函数没?

那个system("  "); 确是你所说的那样,它的退出就是变量死亡的时候,这也学就是我们不能写出真正的bat2exe的原因所在,但我想是我们不知道system的底层代码,我们只是知道有这么一个库函数,就像我们经常用math.h(C或C++)头文件,确连个log函数怎么计算的却不知道(不要告诉我说是泰勒级数,学数值分析时最基本的三角函数也不是用它来计算,想想double要18位精度,在[0pi/4]要展开多上项,还有要多少次乘法运算就可以否定了)

所以我们要真正做点有东西还是得关注底层。。。
作者: plp626    时间: 2009-5-29 22:11

vbs的效率应该和exe不是一个数量等级的
作者: wxcute    时间: 2009-5-29 22:14

意思是不是等同于写一个 expr.bat
再由 expr.bat 来处理其后的参数呢?
作者: defanive    时间: 2009-5-29 22:17     标题: 回复 14楼 的帖子

注意到没有,我的那个Expr中调用了Eval函数,也就是说,Call Expr a abs(-1)也是允许的
所以vbs中的所有数学函数,哪怕MsgBox这些函数都是允许的。。。
作者: defanive    时间: 2009-5-29 22:23     标题: 回复 14楼 的帖子

关注底层,直接去找API吧,微软未公布的API还有好几千个呢

至于数学函数,批处理都可以做到。给我时间,浮点数幂运算批处理也可以做到
作者: Batcher    时间: 2009-5-29 22:27     标题: 回复 7楼 的帖子

计算机专业的学生有很大一部分要学《编译原理》这门课,于是,用C语言实现中缀表达式、前缀表达式等等都是必做的作业之一嘿嘿,飘过~

学学《编译原理》,还是能有很多收获的。个人感觉,对于代码级别的调优,没有《编译原理》做功底可不行 : )
作者: defanive    时间: 2009-5-29 22:47

还是巡查功底深厚。。。
作者: netbenton    时间: 2009-5-29 22:48

其实浮点运算,在现行批处理应用中,用到的时候太少了。并且用三方辅助运算的话,得到的结果批处理并不“认识”它,就算是再进行简单的加一操作,批处理也不能做,
如果该结果不是终结果的话,还要交结三方去处理,如此,批处理频繁的调用三方,该批处理程序的效率肯定不高。这就成了主要工作是由那个三方工具来做了,这样的话还不如直接用其它语言来完成了。
作者: netbenton    时间: 2009-5-29 23:10

在dos 6.22以前是可以在exe程序里直接操作环境变量的,现在的cmd,就不得要领了,而且在使用变量延迟后,更是不知变量在内存中的位置了。直接操作环境变量似乎是不可能了。
看来还是要通过显示输出,或临时文件方法把结果传回给BAT了。
作者: defanive    时间: 2009-5-29 23:21

嗯,反正exe执行完毕后变量都销毁掉了,很是麻烦
作者: Kiming    时间: 2009-5-30 07:21

好深奥的问题 已经讨论到内核了
作者: 随风    时间: 2009-5-30 14:21

实在没搞懂诸位的意思,楼主能解答下我5楼的回帖么?
我也有16楼一样的疑问。你们是一定要写一个exe的函数吗?如果可以是bat文件的话,好像没什么问题啊? call expr.bat ret=fun2(fun(数1,数2)) 只是多写了个call 而以很麻烦吗?
作者: plp626    时间: 2009-5-30 22:35

原帖由 随风 于 2009-5-30 14:21 发表
实在没搞懂诸位的意思,楼主能解答下我5楼的回帖么?
我也有16楼一样的疑问。你们是一定要写一个exe的函数吗?如果可以是bat文件的话,好像没什么问题啊? call expr.bat ret=fun2(fun(数1,数2)) 只是多写了个call  ...


就是多了一些临时变量,对于简单的问题这个体会不会有多深,复杂点的就难以忍受了

这个帖子:
http://bbs.bathome.net/thread-4716-1-1.html
试着用递归写个排列组合,你就知道批有多麻烦
作者: plp626    时间: 2009-5-30 22:38

原帖由 wxcute 于 2009-5-29 22:14 发表
意思是不是等同于写一个 expr.bat
再由 expr.bat 来处理其后的参数呢?


最好能直接写个expr.exe 来处理后面的参数,只是这个目前看来难度颇高,目前能想到的就是,借助expr.bat分解参数,再让expr.exe去处理基本任务,然后把expr.exe的输出结果给expr.bat
作者: slore    时间: 2009-6-3 13:52

如果fun2是个输出语句

fun2(fun(1,2))

输出 fun(1,2) 和 输出fun的结果如何区别呢?

BAT里面没有说限定字符串要"..",所以引号本身可以输出。。。
其实牵扯的问题比较多,如果你强制加个要求。。。来区分感觉和为了方便又背道而驰了

最好能通用,在原P上加这个能调用而不要改变过多。。。


其实plp626你。。。
怎么说呢,觉得P和汇编有点像。。。
汇编毋庸置疑强大。。。
但是他也不支持函数的套用吧。
就是标签,就是跳转。。。


要是写出来,移植性也比较差。

要么发展下去。。。为一种新型脚本,不再是BAT
作者: plp626    时间: 2009-6-15 09:16

........................

[ 本帖最后由 plp626 于 2009-6-15 09:25 编辑 ]
作者: plp626    时间: 2009-6-15 09:24

原帖由 slore 于 2009-6-3 13:52 发表
如果fun2是个输出语句

fun2(fun(1,2))

输出 fun(1,2) 和 输出fun的结果如何区别呢?

BAT里面没有说限定字符串要"..",所以引号本身可以输出。。。
其实牵扯的问题比较多,如果你强制加个要求。。。来区分感 ...


怎么说呢,不知端午节时我是怎么想到发的这个帖子。。。
只是觉得cmd的功能不能让我们随心所欲,就目前的cmd的功能只觉的方便流程控制,做此外的事情,大多是小题大作了,所以看我这个帖子,大家一定感觉小题大作到了尽头,只是不知尽头之后是什么---------仁者见仁智者见智了

我如果在微软并且技术过硬就好了,我一定赋予cmd一个可以让大家可以“随心所欲”的功能




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