标题: [系统相关] [讨论]分离%path%路径的一段批处理 [打印本页]
作者: namejm 时间: 2009-5-18 22:12 标题: [讨论]分离%path%路径的一段批处理
曾经在CN-DOS上看到ansipeter同志(曾用马甲:9527、bigpipe)发表的一段代码,可以很方便地分离出%path%中的每一条路径,揣摩良久,不得其解,发布在此,望各位能详加探讨其中奥妙:- for %a in ("%path:;=" "%") do @echo %~a
复制代码
原帖出处:http://www.cn-dos.net/forum/viewthread.php?tid=38347
作者: netbenton 时间: 2009-5-18 22:21
若path=c:\dos;c:\windows;c:\tools
echo %path:;=" "%
结果为:c:\dos" "c:\windows" "c:\tools
echo "%path:;=" "%"
结果为:"c:\dos" "c:\windows" "c:\tools"
原来是这么回事!后面的%~a再把双引号丢掉。
作者: namejm 时间: 2009-5-18 22:33
哈哈,真是一语点醒梦中人,竟然是用引号对来分隔字符串,而不再采用常见的空格做分隔符——为了兼容路径中可能出现的空格,只能舍弃空格做分隔符。
作者: Batcher 时间: 2009-5-18 22:33
原帖14楼有讲解,跟2楼差不多。
作者: tireless 时间: 2009-5-18 22:38
直接 for %a in (%path%) do echo %a 可以分出来。括号里面的分隔符可以是 ; , =
作者: namejm 时间: 2009-5-18 22:39
惭愧,没仔细看那个帖子的所有讨论,错过了领会其中奥妙的大好时机。
作者: namejm 时间: 2009-5-18 22:41
原帖由 tireless 于 2009-5-18 22:38 发表
直接 for %a in (%path%) do echo %a 可以分出来。括号里面的分隔符可以是 ; , =
碰上带空格的路径就会出错,还是顶楼的代码比较保险——当然,顶楼的代码也不能兼容带&的路径,不过,在实际使用中,是可以通过一些技巧避免掉的。
—————————————————————————————————————————————————————————
红色部分是错误的结论,实际上,顶楼的代码可以兼容带&的路径,请看以下楼层中batcher的演示。
作者: Batcher 时间: 2009-5-18 22:41 标题: 回复 5楼 的帖子
3楼已经提到空格问题了
作者: Batcher 时间: 2009-5-18 22:48 标题: 回复 7楼 的帖子
C:\Test>test.bat
C:\BatHome\Batcher&namejm
C:\BatHome\Batcher namejm
C:\Test>type test.bat
@echo off
set "mypath=C:\BatHome\Batcher&namejm;C:\BatHome\Batcher namejm"
for %%a in ("%mypath:;=" "%") do (
echo %%~a
)
|
作者: netbenton 时间: 2009-5-18 22:49
开启变量延迟后,用!号代替%号,就可以解决多个特殊符号问题了
作者: namejm 时间: 2009-5-18 22:59
开启了变量延迟后再用!来代替%,往往会造成原有的!丢失,请看这篇文章:最大限度原样输出含特殊符号的指定行内容:http://bbs.bathome.net/viewthread.php?tid=4580
作者: netbenton 时间: 2009-5-18 23:07
可以在for内把变量延迟关掉就不会丢了- @echo off&setlocal enabledelayedexpansion
- for %%a in ("!path:;=" "!") do (
- if "!#@#!" equ "" endlocal
- echo %%~a
- )
复制代码
[ 本帖最后由 netbenton 于 2009-5-18 23:08 编辑 ]
作者: namejm 时间: 2009-5-18 23:17
netbenton兄12楼的代码测试过了吗?我实地测试了一下,修改之前的代码,执行结果显示的是"echo 处于关闭状态"的报错信息。
另外,在for内,启用了变量延迟后,可以在合适的位置用endlocal来中止,就可以避免!被抛弃的问题,但是,这个合适的位置在什么地方呢?我认为,应当满足以下条件:
1、setlocal和endlocal要配对使用:开启一次之后,再关闭;关闭之后,在进入for的下一次内部循环时,再开启一次,结束之时再关闭,但一定要保证开关的次数要对应;
2、setlocal可以在for语句之前,也可以包含在for语句中,但是,一定要保证它们开关的次数要对应。
作者: namejm 时间: 2009-5-18 23:27
尝试把if语句去掉,直接endlocal,发现代码也能正确执行,有点匪夷所思——我有点奇怪 "!#@#!" 的来历:为什么是这么一串突兀的字符串呢?能说说理由吗?
作者: netbenton 时间: 2009-5-18 23:28
测试过了,可以呀,
if "!#@#!" equ "" endlocal
是为了判断是否开启了变量延迟的(要保证不存在#@#变量)
我知道是要一一对应的,且可以在for 之前开启,在for内关闭,并不一定要在一个for内开就得在该for内关的,只要能做到一一对应就可以了。
在for前开,在for内关,有时会有意想不到的效果哦。
作者: netbenton 时间: 2009-5-18 23:31
re 14 楼
#@#是一个不存在的变量,如是开启了变量延迟,就会替换为空了,否则就是!#@#!
作者: namejm 时间: 2009-5-18 23:31
在for前开,在for内关,开关的次数没有一一对应,竟然也不会出现“已达最大递归层”的错误,有点意外,我有点糊涂了,哪位来分析一下,说不定又会有新的突破^_^。
作者: 随风 时间: 2009-5-21 23:45 标题: 回复 17楼 的帖子
提示“最大递归层错误”是连续运行setlocal 32次,而非endlocal
其实12楼的代码完全可以取消if语句,直接endlocal就可以,不过感觉多余^_^
而且反复运行endlocal语句,始终感觉不太“健康”
- setlocal enabledelayedexpansion
- for %%a in ("!path:;=" "!") do (
- endlocal
- echo %%~a
- )
- pause
复制代码
作者: lovealei 时间: 2011-8-25 10:51
上面列出的内容可以输出到文本文件吗?
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |