[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]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
复制代码

理解是对的,但太绕了,4到7行可以简化成:
  1. (set /p"=name="
  2. for %%a in (%%i) do @<nul set /p"=%%%%a"
  3. echo,)<nul
复制代码
----------------------------------------------------
再提供另一种将等号替换为其他字符的方法,无法区分单个等号和连续多个等号,简单来说基本原理是这个:
  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: =%%
复制代码
而为了兼容其他分隔符和各种特殊字符,还要用到另一个帖子的办法:
[分享]区分引号内外,转义特殊字符

TOP

回复 2# CrLf


    谢谢分享,只是显示的话用你的优化效果非常不错,我里面其实是截取的一部分代码,这是第一个步骤,其实你应该已经猜到了,那其实是一些汉字的uri编码,将其转成可以转码的字符后就可以得到真实文字了。这个例子也是从手机导出名片文件中截取的,它来自于vcf文件。

先学习一下你的分享链接,看看又能收获到什么惊喜……

TOP

回复 2# CrLf


    不知是不是系统差异,我这里加上/f反而还有错误提示,
  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: =%%
复制代码
去掉反而正常。
  1. @echo off
  2. for %%a in (^"=E5=AE=89=E8=A1=A3=E6=9F=9C=E9=97=A8=E5=B8=88=E5=82=85^") do set name=%%a
  3. call echo name=%%name: =%%
  4. pause
复制代码

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

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

TOP

回复 5# CrLf

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

TOP

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

回复 5# CrLf


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


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

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

回复 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

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

TOP

回复 10# amwfjhh


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

TOP

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

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

回复 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

返回列表