![]() |
中国DOS联盟-- 联合DOS 推动DOS 发展DOS --联盟域名:www.cn-dos.net 论坛域名:www.cn-dos.net/forum |
| 游客 | 登录 | 注册 | 会员 | 搜索 | 中国DOS联盟 |
|
中国DOS联盟论坛 现在时间是 2026-09-14 17:22 |
共 47,812 主题排行 / 349,917 发帖 / 今日 0 篇 / 48,268 会员排行 |
| DOS批处理 & 脚本技术(批处理室) » [讨论]如何从用户传入的参数中去掉引号? |
| 可打印版本 13,607 / 23 |
| 第1楼 wingofsea | 发表于 2006-05-26 16:03 |
| 初级用户 发帖 34 积分 124 | |
|
[讨论]如何从用户传入的参数中去掉引号? 批处理获取到用户输入的参数,如
utility "C:\program files\utility", 如何去掉"C:\program files\utility" 的引号? 要做一些字符串拼接的操作,如 @echo off @set arg=%1 @set file_path=%arg%\readme.txt @for /f "usebackq delims=" %%a in (%file_path%) do set a=%%a 运行上诉代码提示: The system cannot find the file C:\Program Files\utility"\version.txt 请问如何解决? ───────────────── 版主提示 ───────────────── 本主题讨论小结如下: 很多情况下,我们需要脱除一个字符串中可能会存在的引号,然后在加上自己的引 号使其中的特殊字符(命令连接符& 、| 、&&、||,命令行参数界定符Space 、tab 、 ; 、= ,字符化转义符^ 、" ,变量化转义符% 等)字符化,失去特定的作用,而作为 普通的字符成为字符串的一个组成部分。 一、将字符串中的引号脱去的简单办法有三种,它们的功能相近,只是各自的使用 场合不同,可以处理大多数的情况。 1-1 、如果字符串存在于命令行参数%1中,可以使用%~1 脱去第一对外侧引号,如 果没有外侧引号则字符串不变; 1-2 、如果字符串存在于for 替代变量%%i 中,可以使用%%~i脱去第一对外侧引号, 如果没有外侧引号则字符串不变; 1-3 、如果字符串存在于环境变量%temp%中,可以使用%temp:"=% 脱去其中所有的 引号,如果没有引号则字符串不变; 1-4 、以上三种方案在某种程度上可以互相通用,因为它们作为变量的一种类型, 可以通过类似以下的代码或代码片断相互转移: 1-4-1、for替代变量转命令行参数: call:DeQuote %%i 1-4-2、环境变量转命令行参数:call:DeQuote %temp% 1-4-3、命令行参数转for替代变量:for %%i in (%1) do ... 1-4-4、环境变量转for替代变量:for %%i in (%temp%) do ... 1-4-5、命令行参数转环境变量:set temp=%1 1-4-6、for替代变量转环境变量:for ... set temp=%%i 二、如果字符串的引号分布情况很复杂,或者我们对被脱去引号的位置有特殊要求, 或者字符串中可能出现某些控制字符,则可以将字符串首先通过1-4 中的对应方法转存 至环境变量中,在使用以下方案或其组合进行处理: 2-1 、可以使用set var=%var:~1%脱去环境变量var 串首的第一个引号,如果串首 不存在引号则第一个字符被脱去; 2-2 、可以使用set %var:*"=% 脱去环境变量var 串首的第一个引号,如果串首不 存在引号则变量值不变; 2-3 、可以使用set var=%var:~0,-1% 脱去环境变量var 串尾的最后一个引号,如 果串尾不存在引号则最后一个被脱去; 2-4 、可以使用set "var=%var%脱去环境变量var 串尾的最后一个引号,如果串尾 不存在引号则环境变量被清空; 2-5 、可以使用set var=%var:~1,-1% 脱去环境变量var 串最外侧的一对引号,如 果串外侧不存在引号则外侧一对字符被脱去; 2-6 、可以使用%var:*"=set "var=%脱去环境变量var 串最外侧的一对引号,如果 串外侧不存在引号则出现语法错误; 2-7 、可以使用set "var=%var:"=%"脱去环境变量var 串中可能出现的所有引号, 如果串外侧不出现引号则变量值不变;与1-3 不同的是,它容许字符串的匹配引号对内 出现特殊控制字符; ───────────────── 版主提示 ───────────────── [ Last edited by willsort on 2006-5-28 at 22:52 ] |
|
| 第2楼 bagpipe | 发表于 2006-05-26 17:01 |
| 银牌会员 发帖 425 积分 1,144 来自 北京 | |
|
@echo off
set arg=%1 echo %arg:"=% set file=%arg:"=%\1.txt echo %file% for /f "usebackq" %%a in ("%file%") do echo %%a 其实很简单,就是没有想到罢了............. |
|
| 第3楼 无奈何 | 发表于 2006-05-27 00:00 |
| 荣誉版主 发帖 356 积分 1,338 | |
|
用 CMD 变量的扩展特性不行吗?
set arg=%~1 这样可以去掉首尾的双引号。 |
|
| 第4楼 bagpipe | 发表于 2006-05-27 14:57 |
| 银牌会员 发帖 425 积分 1,144 来自 北京 | |
|
为什么我老是找不到最佳方法呢?伤心.........受教中.............
|
|
| 第5楼 willsort | 发表于 2006-05-27 18:17 |
| 元老会员 发帖 1,512 积分 4,432 | |
|
Re 无奈何:
实际上,这个问题还要比你我想象的要复杂一些。 首先,bagpipe兄的代码更适合脱去环境变量的引号,而兄的代码则更适合脱去命令行参数的引号,二者互有所长。 其次,无论是哪种方法,都存在无法切实约束串内特殊字符的缺点。 比如,有变量test1="C:\Program files",而如果使用兄的方法,则files将丢失;又比如,有变量test2="echo test>sample.txt",无论使用何种方法,都会导致程序意外产生的垃圾文件。 这我在namejm兄的主题曾略有提及,只是语焉不详,现在在这里提出,作为一个课题讨论一下,欢迎各位版主达人不吝赐教。 [ Last edited by willsort on 2006-5-27 at 21:26 ] |
|
| 第6楼 3742668 | 发表于 2006-05-27 19:08 |
| 荣誉版主 发帖 718 积分 2,013 | |
|
俺也来抛个砖:
对于字符串内有多个引号的问题无法处理,不过可以先对字符串内除了开头和结尾的引号进行转换,完了再转换回来就行了。只是抛个砖,希望能引出willsort和无奈何两位的玉出来。。 |
|
| 第7楼 无奈何 | 发表于 2006-05-27 19:28 |
| 荣誉版主 发帖 356 积分 1,338 | |
|
TO willsort
兄的这段代码调用有些问题。变量值中含有引号,并作为参数传送时,参数不要用引号扩起来。这样潜在的问题是不容易确定变量值中是否含有引号,所以我习惯的做法是用 %~n 脱去引号,然后再加上引号。
|
|
| 第8楼 willsort | 发表于 2006-05-27 22:06 |
| 元老会员 发帖 1,512 积分 4,432 | |
|
Re 无奈何:
我的意思是,当我们无法预知test1/test2的串值中是否含有引号时,就无法使用特定的方法对其中的特殊字符进行约束。比如namejm兄代码中source变量,是通过set /p获取的,我们无法确知执行代码的用户有没有使用引号,或者会不会有意无意给我们的代码制造麻烦。 也就是说,当串值(不仅仅是环境变量)含有引号时,我们(在各种命令行下)引用它就不能再使用引号,而当串值不含引号时,我们又需要使用引号进行约束,而这还没有考虑到两对或更多对引号甚至奇数个引号出现的情形。而因为我们无法预先获知串值的内容,所以需要预先检测,而目前所知的任何检测都需要引用串值。引用前需要检测,检测时必须引用,这就形成了一个佯谬。 感觉上,这个问题实际上是来源于CMD匹配引号采用就近匹配,而不是就远匹配的原则。我想知道是否存在一个比较另类的办法可以解决这个问题。 Re 3742668: 你的 %tmpVar:*"=set "ret=% 一句确实妙绝,对星号在此处的用途尚不十分清楚,不知可否解释一二? 当然它也需要预先确定串值外含有引号,否则语法错误。 Re All: 目前的测试中,set "ret=%test%会将含有后引号的串值脱去一个后引号,这是可预期的结果;而没有引号的串值将整个脱去,就在意料之外了,我本猜想它会将ret=%test%作为环境变量名的一部分,因变量匹配无效而不对%ret%做任何修改的,而结果是%ret%被清除。 |
|
| 第9楼 3742668 | 发表于 2006-05-27 22:51 |
| 荣誉版主 发帖 718 积分 2,013 | |
|
Well,我就按willsort兄的要求向不大了解set命令中*号作用的朋友做个简介吧:
%PATH:str1=str2% "str1" 可以以星号打头;在这种情况下,"str1" 会从扩展结果的开始到 str1 剩余部分第一次出现的地方,都一直保持相配。 所以,在本例中会匹配第一个引号,如果不加*号的话,那么将会匹配所有的引号,那么得到的结果将是错误的。 |
|
| 第10楼 无奈何 | 发表于 2006-05-27 23:21 |
| 荣誉版主 发帖 356 积分 1,338 | |
|
Re willsort
理解兄的意思了,能够办到替换串值中的所有引号,相应的问题是在传输时必须加引号扩起来。 set test="C:\Pro&gram" files" set "test=%test:"=%" call :DeQuote "%test1%" Re 3742668 兄对 * 的解释不太好理解,可以分开来表述。 1、%PATH:str1=str2% 2、%PATH:*str1=str2% 其中 1 替换 PATH 中所有 str1 为 str2 ; 2 替换 PATH 中开始到 str1 部分为 str2 。 再者 echo %var:*.=#% 输出结果应该是:#cn-dos.net |
|
| 第11楼 willsort | 发表于 2006-05-27 23:33 |
| 元老会员 发帖 1,512 积分 4,432 | |
|
Re 3742668:
受教了!也已从set /?中找到了相关信息,看来自己还需要复习数遍命令行帮助文档了。 也就是说星号在此的作用,仍然与文件名中的通配作用相似,它可以通配0到多个任意字符。只是类似的单字符通配符?尚不被支持,而且星号的位置只限于串首,不能在串中或串后出现。 |
|
| 第12楼 3742668 | 发表于 2006-05-27 23:37 |
| 荣誉版主 发帖 718 积分 2,013 | |
|
嗯,谢谢无奈何指出毛病。关于*的解释嘛,不能怪我,要怪microsoft的 帮助与支持 写得不太好理解。心浮气躁,离大成始终差那么一步,呵呵。
|
|
| 第13楼 Climbing | 发表于 2006-05-27 23:42 |
| 铂金会员 发帖 2,753 积分 6,962 来自 河北保定 | |
|
TMD,微软的命令说明简直就象绕口令(估计他们自己也没有搞明白到底该如何说),还是3742668兄的例子来得简明易懂一些。说白了,str1前加*号,那么就会只替换环境变量中第一个出现的str1,其它的就不替换了,是这意思吧?
|
|
| 第14楼 willsort | 发表于 2006-05-28 00:49 |
| 元老会员 发帖 1,512 积分 4,432 | |
|
Re Ups:
有意思的一个发现,由于密集回复导致从10楼到13楼都变成了隔层回复,不知是由于论坛同步延迟的原因,还是用户刷新延迟的问题。 另外,还不是很明白无奈何兄set "test=%test:"=%"之后再去call :DeQuote "%test1%"的缘由。 最后,就此主题略作一个小结,请大家补正: 很多情况下,我们需要脱除一个字符串中可能会存在的引号,然后在加上自己的引号使其中的特殊字符(命令连接符&、|、&&、||,命令行参数界定符Space、tab、;、=,字符化转义符^、",变量化转义符%等)进行字符化,使其失去特定的作用,而作为普通的字符成为字符串的一个组成部分。 一、将字符串中的引号脱去的简单办法由三种,它们的功能相近,只是各自的使用场合不同,可以处理大多数的情况。 1-1、如果字符串存在于命令行参数%1中,可以使用%~1脱去第一对外侧引号,如果没有外侧引号则字符串不变; 1-2、如果字符串存在于for替代变量%%i中,可以使用%%~i脱去第一对外侧引号,如果没有外侧引号则字符串不变; 1-3、如果字符串存在于环境变量%temp%中,可以使用%temp:"=%脱去其中所有的引号,如果没有引号则字符串不变; 1-4、以上三种方案在某种程度上可以互相通用,因为它们作为变量的一种类型,可以通过类似以下的代码或代码片断相互转移: 1-4-1、for替代变量转命令行参数: call:DeQuote %%i 1-4-2、环境变量转命令行参数:call:DeQuote %temp% 1-4-3、命令行参数转for替代变量:for %%i in (%1) do ... 1-4-4、环境变量转for替代变量:for %%i in (%temp%) do ... 1-4-5、命令行参数转环境变量:set temp=%1 1-4-6、for替代变量转环境变量:for ... set temp=%%i 二、如果字符串的引号分布情况很复杂,或者我们对被脱去引号的位置有特殊要求,或者字符串中可能出现某些控制字符,则可以使用以下方案: 2-1、可以使用%test:*"=%脱去环境变量test串首的第一个引号,如果串首不存在引号则变量值不变; 2-2、可以使用set "test=%test%脱去环境变量test串尾的最后一个引号,如果串尾不存在引号则变量值被清空; 2-3、可以使用%test:*"=set "test=%脱去环境变量test串最外侧的一对引号,如果串外侧不存在引号则出现语法错误; 2-4、可以使用set "test=%test:"=%"脱去环境变量test串中可能出现的所有引号,如果串外侧不出现引号则变量值不变;与1-3不同的是,它可以容许字符串的匹配引号对内出现特殊控制字符。 [ Last edited by willsort on 2006-5-28 at 01:22 ] |
|
| 第15楼 无奈何 | 发表于 2006-05-28 01:05 |
| 荣誉版主 发帖 356 积分 1,338 | |
|
Re willsort
总结的很详细,大众的智慧是无穷的^_^。 关于 call :DeQuote "%test1%" 只是想说明当串值中含有特殊字符时,在传递和调用的过程中必须加引号以使其失去特殊性。不然会解释为多个参数或多个命令。 |
|
| 1 2 下一页 |
|
[ 联系联盟系统管理团队 -
中国DOS联盟 -
标准版 ] Sponsored by ifanr Inc | © 2001–2023 |