[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[文本处理] 批处理中如何用set对=等号进行替换

本帖最后由 pcl_test 于 2016-9-8 12:50 编辑

有下方类似样本文本,其中主体信息部分含大量=号,需要将其改变为其它字符以作后续处理:
list.txt
  1. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=A6=88
  2. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E6=AF=9B=E5=93=A5
  3. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=A6=B9=E5=A6=B9
  4. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E4=BA=8C=E4=B8=87
  5. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E6=96=B0=E4=B8=AD=E6=BA=90
  6. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=B0=8F=E7=BF=A0
  7. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=B0=BE=E5=B7=B4
  8. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E7=88=B8=E7=88=B8
  9. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E4=BC=8D=E5=B8=88=E5=82=85
  10. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=B0=8F=E7=BD=97
  11. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E7=89=A9=E7=AE=A1
  12. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85
  13. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=86=92=E8=8F=9C
  14. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=8C=85=E8=BA=AB=E5=B7=A5
  15. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=BF=83=E5=AE=BD=E4=BD=93=E8=83=96
  16. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=B0=8F=E9=B1=BC
  17. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E8=B1=86=E6=B1=A4
  18. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=B0=8F=E8=8D=89
  19. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E4=B9=8C=E9=B8=A6
  20. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E8=B0=A2=E5=A4=84
  21. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E9=91=AB=E9=91=AB
  22. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E8=90=A7=E8=90=A7=E9=BA=BB=E5=B0=86
  23. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=A4=9C=E7=8C=AB
  24. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E8=A5=BF=E6=9C=8D
  25. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E6=B1=AA=E6=B1=AA
  26. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=9B=9B=E4=B8=AA=E5=9C=88
  27. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E7=A7=8B=E7=A7=8B
  28. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E5=B0=8F=E7=BE=A9
  29. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E9=99=88
  30. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=E9=9D=92=E8=9B=99
  31. FN;CHARSET=UTF-8;ENCODING=QUOTED-PRINTABLE:=31=32=E6=A0=8B
复制代码
拿到题目后一看文本替换自然想到用set, 但具体实施的时候出问题了:SET中文本替换不能对=字符进行处理,试过很多办法,转义=号,转义"号都不起作用,正一筹莫展的时候突然想到论坛里面讨论过对于delims的默认取值及DOS默认分割符的相关讨论,=号正是经典分割符之一,比如echo,for 等均可以识别其为正确分割符,既然如此,就想到以下相对绕弯的方法来达到对set语句中=号替换的作用,如下方代码,就以%号来替换文本中的=号,核心语句恰好也是用的set本家的招式:
  1. @echo off
  2. for /f "tokens=2 delims=:" %%i in (list.txt) do (
  3.   
  4.   for /f "usebackq tokens=*" %%k in (`"(for %%a in (%%i) do @<nul set /p=%%%%a)&echo,"`) do (
  5.     set name=%%k
  6.     call,echo,name = %%name%%
  7.   )  
  8. )
  9. pause
  10. goto :EOF
复制代码

  1. mshta http://bathome.net/s/hta "type('list.txt').replace(/[^:\r\n]+(?=([\r\n]|$))/g, function($0){return decodeURIComponent($0.replace(/=/g,'%%'))})"
  2. pause
复制代码

TOP

擦喇!灵异事件。
第三个FOR存在时,第四个FOR不报错;第三个FOR用REM注释起来时,第四个FOR就会报找不到文件错误。
彻底凌乱了……

TOP

回复 15# CrLf


    你举这个例子也从侧面印证了/f时对括号里面的判断,首字节为'时识别为命令,即使里面是一个“看起来是标准字符串”的字符串,带引号字符串与不带引号字符串具有同等效力,只要包含正确命令,都会被执行,区别只是第二句命令被双引号包起来,所以对其中的特殊符号进行了转义,=不再作为分割符。但是echo后的第一字节,[,;= ]等组合还是会被识别成切割符(这是构成命令的要素),不管在双引号内与否,因为这句的最外层是',里面有符合命令特征的,就先按语法解析了。

把几句放到一起看或许更能说明问题,出错在语法解析这一步上:预处理给出了一个可以显示的结果(兼具了命令与字符串二者的特征),但在语法解析时出了问题,既给出了可见回显,又提示文件错误……
  1. prompt $
  2. echo on
  3. for /f "delims=" %%a in ('echo;=E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85') do echo,%%a
  4. for /f "delims=" %%a in ('"echo+=E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85"') do echo,%%a
  5. for /f "delims=" %%a in ("=E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85") do echo,%%a
  6. for /f "delims=" %%a in (^"=E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85^") do echo,%%a
  7. pause
复制代码

TOP

回复 14# amwfjhh


我觉得你想复杂了...个人理解,cmd 只是在预处理中把 for~do 之间未转义的分隔符转换成空格,等号就是在预处理中变成空格的
然后当执行到 for 命令的时候,再去检查 in~do 之间的字符串首尾字符,此时已经没有转义的概念了
把这几句保存到 bat 中,回显就是初步的预处理结果
  1. echo on
  2. for /f "delims=" %%a in ('echo =E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85') do echo %%a
  3. for /f "delims=" %%a in ('"echo =E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85"') do echo %%a
  4. pause
复制代码

TOP

本帖最后由 amwfjhh 于 2014-12-4 15:50 编辑

For循环,in后面的条件括号很有意思啊。不知道它具体是怎么工作的。
不开/f开关只认文件与字符两种办理,非文件即字符,即使输入'echo hello'这种语句也被识别为字符串,并且还是断行输出(识别空格为分割符,这里'显然被识别为普通字符)。
开/f开关后会识别三种,字符,命令与文件。回车 兄构建的这个代码
  1. for /f "delims=" %%i in (^"=E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85^") do set "str=%%a"
复制代码
或许可以胡乱猜一下,出错的提示为打开文件错误,显然先试着解析的是文件(或许之前先排除过命令,因未找到'而转向下一个处理),并且每次运行提示的文件打开错误内容还不一样,此处可能发生了内存泄漏,文件名指向了一块无意义内存区,然后因找不到而转到下一处理;而后是进行字符串解析(或者命令解析,命令解析会出现不是内部或外部命令的提示,所以这里在第一个字节进行判定的时候即已退出解析而跳至下一阶段),但是如果被作为字符串解析的话,这里已经对"进行了转义,所以str的值应该为带引号的字符串,并且应该完整显示内容,但此处最终被解析的结果来看,引号不见了,等号也被转成空格了(分割符处理),最终的结果类似于echo,=E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85。
那此处的(^"=E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85^")有可能被最终解析成了另一种形式:流

PS:"被转义,它本身失去了转义效能,因此后面的=被识别为分割符而作统一转换,这是=消失的原因,但"为什么消失就想不通了,按说被转义后它应为普通字符而被显示出来,就像不加/f那样,
  1. for %%a in (^"=E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85^") do echo %%a
复制代码
看来/f开关对于字符串的首尾字符是进行宁可错杀,不可放过的政策。

TOP

是。我也就遇题解题,要整出通用性的东西来那是大牛们才能干的事。

TOP

回复 10# amwfjhh


    这种方法始终是有局限性,在实际文件的处理中我们不知道会有哪些字符会出现。

TOP

Win7用户表示鸭梨不大
  1. @echo off
  2. powershell -c "(gc a.txt) -replace '=', '%%'" > b.txt
复制代码

TOP

回复 9# DAIC


    这倒可以利用先将空格转换的预处理方式来避免。
  1. @echo off
  2. set "src=bbs=bat home=net"
  3. set "src=%src: =@%"
  4. echo src : %src%
  5. for /f "delims=" %%i in ('echo %src%') do (
  6.     set "str=%%i"
  7. )
  8. echo,after for : %str%
  9. call,set "str=%%str: =.%%"
  10. call,set "str=%%str:@= %%"
  11. echo,dst : %str%
  12. pause
复制代码

TOP

回复 2# CrLf


但是如果字符串里面有空格,替换的时候会发生误伤,求指点啊大神。
  1. @echo off
  2. for /f "delims=" %%i in (^"bbs=bat home=net^") do (
  3.     set str=%%i
  4. )
  5. call set str=%%str: =.%%
  6. echo,%str%
  7. pause
复制代码

TOP

本帖最后由 amwfjhh 于 2014-12-4 15:14 编辑

回复 5# CrLf


    你这个转义IN内等号的方法效率很高,可以批量将=消除而不遍历,有没有基于这个方案的将其替换为%的方法呢,消化完你那篇帖子还要段时间……


PS:自己都看晕了。忘了最简单的办法:
  1. set name=!name: =%%!
复制代码

TOP

回复 5# CrLf

还是有错误提示,出处何在?

TOP

明天换台机子试试,还是有报错。

TOP

本帖最后由 CrLf 于 2014-12-3 21:30 编辑

回复 4# amwfjhh


那就试试:
  1. for /f "delims=" %%a in (""=E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85"") do set "name=%%~a"
  2. call echo name=%%name: =[等号]%%
复制代码
不用 /f 比较害怕字符串含 * 或 ?

TOP

返回列表