Board logo

标题: 用一行批处理实现标签跳转 [打印本页]

作者: cjiabing    时间: 2011-8-16 23:44     标题: 用一行批处理实现标签跳转

将含有标签跳转命令的多行代码转换成一行。如:
  1. if exist c:\123.txt (goto a) else (goto b)
  2. exit
  3. :a
  4. echo yes
  5. pause&exit
  6. :b
  7. echo no
  8. pause&exit
复制代码
转换结果示例:
  1. if exist c:\123.txt (goto a) else (goto b)&exit&:a&echo yes&pause&exit&:b&echo no&pause&exit
复制代码
直接用 & 将每一行连接起来了,但无法执行或结果没有达到目标要求。
有何难度?
这个问题看似无法完成,主要是因为在连接标签名时,标签会失效。特别是许多命令,包括标签自身,都是通过行来定义执行的,离开行后命令会失效。
但,也正是不可能实现的问题才放出来挑战各位的思想和技术,希望有人能够实现。
这样做有什么用?
第一、在CMD窗口实现批处理脚本的标签功能。在CMD窗口是无法使用标签的,除非你在CMD窗口调用其他批处理脚本文件,虽然CMD帮助里有“goto/?”。 “cmd /c”命令有个弊端,就是它只支持一行命令参数,有多行就会出错。假如能将将许多命令压缩到一行中,包括标签跳转等,将极大的扩展“cmd /c”命令的使用,这样,大家可以使用cmd命令来取代临时文件。
第二、扩展变量型函数。同样,在变量型函数中,命令同样只能使用一行,不能多行,不能标签,限制了变量函数的应用。假如变量函数能包容更多的批处理脚本命令,将使得变量函数使用更加广泛。
批处理函数的高效另类应用(免call的哦!):http://www.bathome.net/viewthread.php?tid=5861
一些标签实验:
1、如何在标签名前面放置命令?
2、如何执行标签后的命令?
  1. @echo off
  2. goto b
  3. pause
  4. exit
  5. (:b&echo I'am here)
  6. echo U lose
  7. pause&exit
  8. :b
  9. echo U wrong
  10. pause&exit
  11. 有效的标签:
  12. (:b&echo I'am here)
  13. (:b&echo I'am here
  14. :b:aaaaaaaaaaaecho I'am here
  15. ;;;;;;;;;;:b&echo I'am here
  16. ;;;;;;;;;:;;;;;b&echo I'am here
  17. ;;;=;;,;;;   ;:;;=;,;;b&echo I'am here
  18. ;;;=;;,;;;   ;:;;=;,;;b fsdfweer323,.^echo I'am here
  19. 无效(无法执行标签后的命令或者标签无效):
  20. &(:b&echo I'am here)
  21. [:b]
  22. ...:b
  23. :b  (%I'am here%)
  24. :b %echo I'am here%
  25. :b echo I'am here^&echo U lose
  26. ;;;=;;,;;;   ;:;;=;,;;b echo I'am here&echo U lose&pause&exit
复制代码
标签的一些属性
1、独立一行;
2、标签前可以添加一些无意义的符号,如“;    =   :”,而且可以同时使用多个且不影响标签名的有效性,还可将标签的冒号和标签名分开;
3、标签名后可以使用空格、冒号、&、|等少数几个符号分隔,使用其它字符示为标签名的有效组成部分,改变标签;
4、标签名后的命令无法执行,即使使用&也无济于事,因此,可以直接在标签名后写注释。
作者: raymai97    时间: 2011-8-17 00:22

感觉是没法子的~ 不过俺有一个想法。如果情况可以的话,就把
  1. if exist c:\123.txt (goto a) else (goto b)
  2. exit
  3. :a
  4. echo yes
  5. pause&exit
  6. :b
  7. echo no
  8. pause&exit
复制代码
变成
  1. if exist c:\123.txt (echo yes) else (echo no)
  2. pause
  3. exit
复制代码
但问题是,通常都不只是echo这样简单……
“使用cmd命令来取代临时文件”?
俺不是很明白,可不可以给些例子,来证明cmd /c可以取代临时文件?
作者: cjiabing    时间: 2011-8-17 16:13

回复 2# raymai97


    你那个是投机取巧了,无法适应更多情况,至于取代临时文件暂时没有更好的想法。
作者: cjiabing    时间: 2011-8-17 16:44

具体的应用说明
举个简单的例子:
使用AT命令定时执行一串命令,而不必一个BAT
  1. at 16:40 cmd /q /c "%GetPath0%BmpProgram\read.vbs" !Input1! !Input1!&at 16:40 cmd /q /c !Input1!
复制代码

使用一个cmd命令,而不必使用一个bat执行reg:

  1. reg add HKCR\Audio.%%a\shell\PlayList\command /t REG_SZ e /f /d "cmd /q /c echo;"%%1" %%*>>\"!GetPath0!PlayList\PL.txt\"
复制代码

使得start操作更有搞头:
  1. start /b "" cmd /c "(for /l %%a in (%daojs%,-1,0) do @title %%a&ping /n 2 127.0.1>nul&if exist "%temp%\$0.tmp" exit)&&(cd.>"%temp%\$1.tmp")"
复制代码

在以上命令中虽然没有使用到标签跳转,到假如有标签跳转的话,我可以实现更多功能
我在实践中用得比较多cmd和start,所以希望它们能够产生一个类似于bat的效果,发挥更大的作用。
作者: raymai97    时间: 2011-8-17 17:40

回复 4# cjiabing


    这样的话,不如使用类似“start /b "%~0" ray”来start回自己的批处理的一部分,这样就不用担心多行的问题了
比如:
  1. @echo off
  2. if "%1"=="ray" goto ray
  3. start /b "" "%~0" ray
  4. exit
  5. :ray
  6. mode con cols=20 lines=7
  7. echo.
  8. echo 多行不是问题了。
  9. echo.
  10. echo 哈哈。
  11. pause>nul
  12. exit
复制代码

作者: plp626    时间: 2011-8-17 19:49

本帖最后由 plp626 于 2011-8-17 19:50 编辑

批处理源文件的行是以换行符标识的;
硬要一行实现跳转那就强行给标签后面加一个换行符
(但这和回车换行符的道理是一样的,仅仅是视觉上在一行而已):
  1. @echo off
  2. :a【换行符】echo %time%&goto:a
复制代码
  1. :: 保存为create.bat 桌面双击之,就可生成测试代码test.bat
  2. @echo off&setlocal enabledelayedexpansion
  3. set nl=^
  4. (echo @echo off
  5. echo :a!nl!echo %%time%%^&goto:a
  6. )>test.bat
  7. pause
复制代码

作者: cjiabing    时间: 2011-8-17 21:20

回复 5# raymai97

确实可以,都忘记START自身了,和CALL一样吧。
虽然这种方法仍然是批处理脚本文件下使用的,总比临时文件之类的好多了,有很大的用途,基本上足够实践使用了。谢谢!~
假如放到CMD窗口就不好如此了,基于以上,直接在CMD窗口使用标签有点苛刻了,当挑战好了。
修改了一下,多运行几次你会有所发现。
   
  1. @echo off
  2. if "%1"=="ray" goto ray
  3. start /b "" cmd /c "%~0" ray
  4. echo,
  5. call :a
  6. echo [4]
  7. exit
  8. :a
  9. echo [2]
  10. dir /b
  11. call :b
  12. goto :Eof
  13. :ray
  14. set var=0
  15. :loop
  16. set /a var+=1
  17. echo.
  18. echo [1]多行不是问题了。共循环 %var% 次。
  19. echo.
  20. pause>nul
  21. if %var% lss 5 goto loop
  22. exit /b
  23. :b
  24. echo.
  25. echo [3]I'am here
  26. echo.
  27. goto :eof
复制代码

该代码多运行几次偶尔会出现乱码。
作者: cjiabing    时间: 2011-8-17 21:32

回复 6# plp626


    非常好,我进行了测试,初步达到目标!~继续测试看看,添加变量,添加IF,添加新的标签。
作者: cjiabing    时间: 2011-8-17 22:02

回复 6# plp626


    哈哈,改造成功,不过费了点劲。将以下代码改造成后面的一行代码
原代码:
  1. set nb=0
  2. :a
  3. set /a nb+=1
  4. echo %%time%%
  5. if %nb% lss 300 (goto b) else (goto a)
  6. exit
  7. :b
  8. echo OK***************
  9. for /l %%a in (1,1,10) do echo %random%
  10. pause
复制代码

改造后的新代码:一行搞掂!~
  1. :: 保存为create.bat 桌面双击之,就可生成测试代码test.bat
  2. :: 标签名后添加一个!nl!,一个!nl!表示一个回车。
  3. :: 在编辑代码中,百分号要加倍;连接符&需加转移符,变成 ^&。
  4. @echo off&setlocal enabledelayedexpansion
  5. set nl=^
  6. >test.bat (
  7. echo @echo off
  8. echo set nb=0!nl!:a!nl!set /a nb+=1^&echo %%time%%^&^(if %%nb%% lss 300 ^(goto a^) else ^(goto b^)^)^&pause^&exit!nl!:b!nl!echo OK***************^&(for /l ^%%^%%a in ^(1,1,10^) ^do echo %%random%%^)^&^pause
  9. )
  10. call test.bat
  11. echo over
  12. pause
复制代码

作者: CrLf    时间: 2011-8-17 22:52

回复 9# cjiabing


    只是看起来是一行,其实 cmd 从文件读入命令时仍然是以换行符分行的,所以若想在 cmd /c 中直接使用换行符作为参数的一部分,那应该是死胡同
作者: cjiabing    时间: 2011-8-17 23:15

本帖最后由 cjiabing 于 2011-8-17 23:18 编辑

回复 10# CrLf


    看来似乎如此,弄了半天都不得:
  1. @echo on&setlocal enabledelayedexpansion
  2. set nl=^
  3. cmd /v:on  /c (:a!nl!&echo !time!&echo !time!&goto:a)
  4. echo over
  5. pause
复制代码

找不到标签!~
不过有个问题,cmd与bat在流程构造上如此不同,那么,bat是如何使用cmd解释的?
作者: raymai97    时间: 2011-8-17 23:47

回复  raymai97

确实可以,都忘记START自身了,和CALL一样吧。
虽然这种方法仍然是批处理脚本文件下使 ...
cjiabing 发表于 2011-8-17 21:20



    我运行了多次,都没有乱码啊~ 嗯,建议楼主去看看那些以前的帖子,会得到启发哦~ 好像这个start也是看那个“随风”的批处理才想到的~
作者: CrLf    时间: 2011-8-17 23:48

bat 中的标签...好像寒夜说过是碰到跳转才从文本读标签,不知道有没记错
二者的区别更主要体现在对 % 和 ! 的处理上




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