Board logo

标题: [文本处理] [已解决]批处理或VBS如何实现对多个文本文件进查找替换字符串操作 [打印本页]

作者: syqh2010    时间: 2015-2-28 22:54     标题: [已解决]批处理或VBS如何实现对多个文本文件进查找替换字符串操作

本帖最后由 pcl_test 于 2016-7-15 13:07 编辑

感谢apang的帮助!!
根据a.txt中文件名依次修改相应文本内容。用sed、纯批、VBS都行
a.txt中内容为文件名
如:
599978.L
599978.R


文件内容相似如下:(以599978.L为例)
  1. [EdgeCribbingTool]
  2. ToolSpeed=25000
  3. ToolSpeedMaster=25000
  4. Waviness=0.05
  5. [Generating]
  6. ToolSpeed=25000
  7. ToolSpeedMaster=25000
  8. Waviness=0.05
  9. [InitialData]
  10. Diameter=73
  11. Thickness=11.10
  12. [EdgeData]
  13. Type=circle
  14. Diameter=73
复制代码
希望改后效果如下:
  1. [EdgeCribbingTool]
  2. ToolSpeed=25000
  3. ToolSpeedMaster=25000
  4. Waviness=0.05
  5. [Generating]
  6. ToolSpeed=5000
  7. ToolSpeedMaster=25000
  8. Waviness=0.05
  9. [InitialData]
  10. Diameter=73
  11. Thickness=11.10
  12. [EdgeData]
  13. Type=circle
  14. Diameter=80
复制代码
就像用VBA中有FOR遍历,用IF判断一样(只是举个例子,哪种方法快用哪种
  1. for所有文件
  2. if文件名=599978.L then
  3. 条件1
  4. if 找到[Generating] then
  5. if 找到ToolSpeed then
  6. ToolSpeed=原来的值*0.2
  7.   end if
  8. end if
  9. 条件2
  10. if 找到[EdgeData] then
  11.   if 找到Diameter then
  12. Diameter=80
  13.    end if
  14. end if
  15. 条件n
  16.                if***then
  17.                      ****
  18.                end if
  19.    
  20. end if
  21. next
复制代码
希望各位能帮忙,用sed,纯批都行,谢谢!
作者: pcl_test    时间: 2015-2-28 22:59

回复 1# syqh2010
599978.L
599978.R
……
这些文件的扩展名是什么?
作者: syqh2010    时间: 2015-2-28 23:05

回复 2# pcl_test
都是文本文档,用记事本可以直接打开。就跟
599978.txt
599978.txt
123456.txt
123456.txt
一样
作者: pcl_test    时间: 2015-3-1 01:09

回复 1# syqh2010
  1. @echo off
  2. setlocal enabledelayedexpansion
  3. for /f "delims=" %%a in ('type "a.txt"') do (
  4. set n=0
  5. for /f "tokens=1* delims=:" %%b in ('findstr /n .* "%%a"') do (
  6. >$ echo,%%c
  7. if !n! == 1 (
  8. for /f "tokens=2 delims==" %%d in ('type "$"') do set /a s=%%d/5
  9. >>"2.txt" echo,ToolSpeed=!s!
  10. set n=0
  11. ) else (
  12. >>"2.txt" echo,%%c
  13. )
  14. findstr /c:"Generating" $ >nul 2>nul && set n=1
  15. )
  16. del $
  17. move "2.txt" "%%a"
  18. )
  19. for /f "delims=" %%a in ('type "a.txt"') do (
  20. set n=0
  21. for /f "tokens=1* delims=:" %%b in ('findstr /n "EdgeData" "%%a"') do set /a t=%%b+1
  22. for /f "tokens=1* delims=:" %%c in ('findstr /n .* "%%a"') do (
  23. if !n! lss !t! (
  24. >>$1 echo,%%d
  25. ) else (
  26. >>$2 echo,%%d
  27. )
  28. set /a n+=1
  29. )
  30. set m=0
  31. for /f "tokens=1* delims=:" %%e in ('findstr /n .* "$2"') do (
  32. if not !m! == 0 >>$ echo,%%f
  33. set /a m+=1
  34. )
  35. move $ "$2"
  36. for /f "tokens=1* delims=:" %%g in ('findstr /n .* "$1"') do >>$ echo,%%h
  37. >>$ echo,Diameter=80
  38. for /f "tokens=1* delims=:" %%i in ('findstr /n .* "$2"') do >>$ echo,%%j
  39. move "$" "%%a"
  40. del $*
  41. )
  42. pause
复制代码

作者: syqh2010    时间: 2015-3-1 01:14

回复 4# pcl_test
非常感谢您的帮助,我试过后再给你反馈:)
作者: syqh2010    时间: 2015-3-1 01:31

回复 4# pcl_test

谢谢!能达到要求效果!
但感觉速度有些慢,因为实际情况需要同时修改几百个文件,且每个文件有200多行,且条件会多于2个。

如果能快一些,简洁一些(便于添加条件)就完美了!
谢谢!
作者: Batcher    时间: 2015-3-1 09:28

回复 6# syqh2010


    请举例说明条件1、条件2是什么
作者: syqh2010    时间: 2015-3-1 09:41

条件1

                if 找到[Generating] then

                         if 找到ToolSpeed then

                                ToolSpeed=原来的值*0.2

                  end if

                end if

条件2

                if 找到[EdgeData] then

                  if 找到Diameter then

                                Diameter=80

                   end if

                end if
作者: apang    时间: 2015-3-1 17:19

本帖最后由 apang 于 2015-3-2 02:02 编辑

保存为test.bat,与a.txt放在同一目录
  1. @set @n=0;// & cscript -nologo -e:jscript "%~0"<a.txt & pause & exit/b
  2. Path = "D:\\Test\\"
  3. fso = new ActiveXObject("Scripting.FileSystemObject");
  4. while (!WScript.StdIn.AtEndOfStream) {
  5.         f = WScript.StdIn.ReadLine().replace(/^\s+|\s+$/g, "");
  6.         f = Path + f;
  7.         if (fso.FileExists(f)) {
  8.                 objFile = fso.OpenTextFile(f, 1);
  9.                 txt = objFile.ReadAll();
  10.                 objFile.Close();
  11.                 fso.OpenTextFile(f, 2).Write(changeNum(txt))
  12.         }
  13. }
  14. function changeNum(s) {
  15.         s += "\r\n";
  16.         //ToolSpeed 的值乘以0.2
  17.         re1 = /^( *\[Generating][\s\S]+?^ *ToolSpeed *=)(.*)\r\n/im;
  18.         //Diameter 的值修改成80
  19.         re2 = /^( *\[EdgeData][\s\S]+?^ *Diameter *=)(.*)\r\n/im;
  20.         //Type=circle 修改为 Type=rand
  21.         re3 = /^ *Type *= *circle *\r\n/im;
  22.         //[EdgeData] 下面增加一行 PA=5.0
  23.         re4 = /^ *\[EdgeData] *\r\n/im;
  24.         //Wavi开头的行后面加上 -Q
  25.         re5 = /^( *Wavi.*?)(\-Q)? *\r\n/img;
  26.         //删除以Thickness开头的行
  27.         re6 = /^ *Thickness.*\n/img;
  28.         s = s.replace(re1,
  29.                 //加减除修改下面*为+-/
  30.                 function(s0,s1,s2){s2-=0; return s1 + (s2 * 0.2) + "\r\n"}
  31.         );
  32.         s = s.replace(re2, "$1" + "80" + "\r\n");
  33.         s = s.replace(re3, "Type=rand" + "\r\n");
  34.         s = s.replace(re4, "$&" + "PA=5.0" + "\r\n");
  35.         s = s.replace(re5, "$1" + "-Q" + "\r\n");
  36.         s = s.replace(re6, "");
  37.         return s.replace(/\r\n$/, "")
  38. }
复制代码

作者: syqh2010    时间: 2015-3-1 20:02

回复 9# apang

谢谢,您的代码很好用,能快速达到效果。我是新手,研究下再给你反馈,谢谢!
作者: syqh2010    时间: 2015-3-1 21:37

本帖最后由 syqh2010 于 2015-3-1 21:41 编辑

回复 9# apang
再次感谢,代码很好用!

1)偶是小白,授之以鱼不如授之以渔。希望能对代码有些注释,然后自已可以添加修改。
                如:
    s0 = s0.replace(re1, function(s0, s1, s2) {
                  return s1 + s2 * 0.2 + "\r\n"
    s0、s1、s2具体返回哪些值,
    “s2 * 0.2”如何改为原值+200(如新值=原值+500),能+-*/

2)如何添加条件(在可以添加的地方备注下就好了)
   如想将[InitialData]下的Diameter值改为65。模防了下好像不行啊。
   function changeNum(s) {
        s += "\r\n[";
        re = /^ *\[[\s\S]+?(?=^ *\[)/mg;
        re1 = /^( *\[Generating][\s\S]+^ *ToolSpeed *=)(.*)\r\n/im;
        re2 = /^( *\[EdgeData][\s\S]+^ *Diameter *=)(.*)\r\n/im;
        re3 = /^( *\[InitialData][\s\S]+^ *Diameter *=)(.*)\r\n/im;
        此处添加查找项
        s = s.replace(re, function(s0) {
                s0 = s0.replace(re1, function(s0, s1, s2) {
                        return s1 + s2 * 0.2 + "\r\n"
                });
                s0 = s0.replace(re2, "$1" + "80" + "\r\n");
                return s0
                s0 = s0.replace(re3, "$1" + "98" + "\r\n");
                return s0

                此处添加对应修改项
        })
        return s.replace(/\r\n\[$/, "")
}
3)有重复的行可以用此法2次查找。没有重复的行可否直接查找
                如“Type=circle”在文本中是唯一的,如何直接找到并修改为 “Type=rand”

4)如何加入路径
        a.txt和BAT在同一目录下,需处理的文本在另一目录下如E:\mybat\ (最好能支持有空格其它字符的路径名)

5)如有可能,希望能此代码能成为一个模版,变得更实用。有增删改功能
                如:
                在[EdgeData]的下一行写入”PA=5.0"
                检测以“Type”开头的行是否以“-Q”结尾(即Type*-Q),是就退出,不是就添加“-Q”
                删除以”Thinkness"开头的行(能支持行开头有空格,特殊字符最好)
                (sed很容易实现以上功能,能添加sed也行,只要能达到效果)

请恕问题太多,谢谢!!!
作者: apang    时间: 2015-3-1 23:57

回复 11# syqh2010


    代码已修改。想要绝对通用是不可能也不现实的,只能具体问题具体分析
作者: syqh2010    时间: 2015-3-2 10:49

回复 9# apang
非常感谢,代码简洁有效,就是我想要的!

再多问一下:
能否支持模糊匹配文本名?
假如不提供完整的文本名,如a.txt中分别写入以下内容,运行后即将符合的更改?
599978.*
*599978*.L
*555978*.*
谢谢!
作者: syqh2010    时间: 2015-3-2 11:53

回复 9# apang

再请教一下,假如不要a.txt,把文件名直接写在代码中,如何改。
只改下面这句
Path = "D:\\Test\\599978.L"
也能修改,但会出现提示“microsoft****运行时错误,没有权限”
作者: apang    时间: 2015-3-2 18:39

回复 14# syqh2010
  1. @set @n=0;/* & echo off
  2. for /f "delims=:" %%a in ('findstr /bn "\/\*" "%~0"') do (
  3.         more +%%a "%~0" | cscript -nologo -e:jscript "%~0"
  4. )
  5. pause & exit/b & rem */
  6. Path = "D:\\Test\\"
  7. fso = new ActiveXObject("Scripting.FileSystemObject");
  8. while (!WScript.StdIn.AtEndOfStream) {
  9.         f = WScript.StdIn.ReadLine().replace(/^\s+|\s+$/g, "");
  10.         f = Path + f;
  11.         if (fso.FileExists(f)) {
  12.                 objFile = fso.OpenTextFile(f, 1);
  13.                 txt = objFile.ReadAll();
  14.                 objFile.Close();
  15.                 fso.OpenTextFile(f, 2).Write(changeNum(txt))
  16.         }
  17. }
  18. function changeNum(s) {
  19.         s += "\r\n";
  20.         //ToolSpeed 的值乘以0.2
  21.         re1 = /^( *\[Generating][\s\S]+?^ *ToolSpeed *=)(.*)\r\n/im;
  22.         //Diameter 的值修改成80
  23.         re2 = /^( *\[EdgeData][\s\S]+?^ *Diameter *=)(.*)\r\n/im;
  24.         //Type=circle 修改为 Type=rand
  25.         re3 = /^ *Type *= *circle *\r\n/im;
  26.         //[EdgeData] 下面增加一行 PA=5.0
  27.         re4 = /^ *\[EdgeData] *\r\n/im;
  28.         //Wavi开头的行后面加上 -Q
  29.         re5 = /^( *Wavi.*?)(\-Q)? *\r\n/img;
  30.         //删除以Thickness开头的行
  31.         re6 = /^ *Thickness.*\n/img;
  32.         s = s.replace(re1,
  33.                 function(s0,s1,s2){s2-=0;return s1 + (s2 * 0.2) + "\r\n"}
  34.         );
  35.         s = s.replace(re2, "$1" + "80" + "\r\n");
  36.         s = s.replace(re3, "Type=rand" + "\r\n");
  37.         s = s.replace(re4, "$&" + "PA=5.0" + "\r\n");
  38.         s = s.replace(re5, "$1" + "-Q" + "\r\n");
  39.         s = s.replace(re6, "");
  40.         return s.replace(/\r\n$/, "")
  41. }
  42. /* --- Start List ---
  43. 1.txt
  44. 2.txt
  45. 3.txt
  46. --- End List ------ */
复制代码

作者: apang    时间: 2015-3-2 18:41

回复 14# syqh2010


    如果还有其它问题,请更新顶楼内容,或重新发贴




欢迎光临 批处理之家 (http://www.bathome.net/) Powered by Discuz! 7.2