找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 80978|回复: 18

[系统相关] [讨论]分离%path%路径的一段批处理

[复制链接]
发表于 2009-5-18 22:12:18 | 显示全部楼层 |阅读模式
  曾经在CN-DOS上看到ansipeter同志(曾用马甲:9527、bigpipe)发表的一段代码,可以很方便地分离出%path%中的每一条路径,揣摩良久,不得其解,发布在此,望各位能详加探讨其中奥妙:

  1. for %a in ("%path:;=" "%") do @echo %~a
复制代码
  原帖出处:http://www.cn-dos.net/forum/viewthread.php?tid=38347
发表于 2009-5-18 22:21:13 | 显示全部楼层
若path=c:\dos;c:\windows;c:\tools
echo %path:;=" "%
结果为:c:\dos" "c:\windows" "c:\tools

echo "%path:;=" "%"
结果为:"c:\dos" "c:\windows" "c:\tools"

原来是这么回事!后面的%~a再把双引号丢掉。
 楼主| 发表于 2009-5-18 22:33:32 | 显示全部楼层
  哈哈,真是一语点醒梦中人,竟然是用引号对来分隔字符串,而不再采用常见的空格做分隔符——为了兼容路径中可能出现的空格,只能舍弃空格做分隔符。
发表于 2009-5-18 22:33:57 | 显示全部楼层
原帖14楼有讲解,跟2楼差不多。
发表于 2009-5-18 22:38:23 | 显示全部楼层
直接 for %a in (%path%) do echo %a 可以分出来。括号里面的分隔符可以是 ; , =
 楼主| 发表于 2009-5-18 22:39:18 | 显示全部楼层
  惭愧,没仔细看那个帖子的所有讨论,错过了领会其中奥妙的大好时机。
 楼主| 发表于 2009-5-18 22:41:26 | 显示全部楼层
原帖由 tireless 于 2009-5-18 22:38 发表
直接 for %a in (%path%) do echo %a 可以分出来。括号里面的分隔符可以是 ; , =

  碰上带空格的路径就会出错,还是顶楼的代码比较保险——当然,顶楼的代码也不能兼容带&的路径,不过,在实际使用中,是可以通过一些技巧避免掉的。

—————————————————————————————————————————————————————————
  红色部分是错误的结论,实际上,顶楼的代码可以兼容带&的路径,请看以下楼层中batcher的演示。
发表于 2009-5-18 22:41:55 | 显示全部楼层

回复 5楼 的帖子

3楼已经提到空格问题了
发表于 2009-5-18 22:48:05 | 显示全部楼层

回复 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
)
发表于 2009-5-18 22:49:04 | 显示全部楼层
开启变量延迟后,用!号代替%号,就可以解决多个特殊符号问题了
 楼主| 发表于 2009-5-18 22:59:53 | 显示全部楼层
  开启了变量延迟后再用!来代替%,往往会造成原有的!丢失,请看这篇文章:最大限度原样输出含特殊符号的指定行内容:http://bbs.bathome.net/viewthread.php?tid=4580
发表于 2009-5-18 23:07:37 | 显示全部楼层
可以在for内把变量延迟关掉就不会丢了
  1. @echo off&setlocal enabledelayedexpansion
  2. for %%a in ("!path:;=" "!") do (
  3.     if "!#@#!" equ "" endlocal
  4.     echo %%~a
  5. )
复制代码

[ 本帖最后由 netbenton 于 2009-5-18 23:08 编辑 ]
 楼主| 发表于 2009-5-18 23:17:21 | 显示全部楼层
  netbenton兄12楼的代码测试过了吗?我实地测试了一下,修改之前的代码,执行结果显示的是"echo 处于关闭状态"的报错信息。

  另外,在for内,启用了变量延迟后,可以在合适的位置用endlocal来中止,就可以避免!被抛弃的问题,但是,这个合适的位置在什么地方呢?我认为,应当满足以下条件:
  1、setlocal和endlocal要配对使用:开启一次之后,再关闭;关闭之后,在进入for的下一次内部循环时,再开启一次,结束之时再关闭,但一定要保证开关的次数要对应;
  2、setlocal可以在for语句之前,也可以包含在for语句中,但是,一定要保证它们开关的次数要对应。
 楼主| 发表于 2009-5-18 23:27:43 | 显示全部楼层
  尝试把if语句去掉,直接endlocal,发现代码也能正确执行,有点匪夷所思——我有点奇怪 "!#@#!"  的来历:为什么是这么一串突兀的字符串呢?能说说理由吗?
发表于 2009-5-18 23:28:10 | 显示全部楼层
测试过了,可以呀,
if "!#@#!" equ "" endlocal
是为了判断是否开启了变量延迟的(要保证不存在#@#变量)

我知道是要一一对应的,且可以在for 之前开启,在for内关闭,并不一定要在一个for内开就得在该for内关的,只要能做到一一对应就可以了。

在for前开,在for内关,有时会有意想不到的效果哦。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-3-17 22:32 , Processed in 0.021595 second(s), 8 queries , File On.

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表