Board logo

标题: [文本处理] 【已解决】批处理实现多条目多内容同时替换 [打印本页]

作者: zhengwei007    时间: 2024-5-18 13:13     标题: 【已解决】批处理实现多条目多内容同时替换

本帖最后由 zhengwei007 于 2024-5-29 16:56 编辑

我有个几千行的源文本text.txt,里面内容大概如下:
  1. a,Recipe: Piece Bone Gaiters    1    59%\\nLeather Helmet Design    1    38%\\nRecipe: Piece Bone Breastplate    1    37%\0
  2. a,Thread    2 - 3    100%\\nRecipe: Piece Bone Gaiters    1    59%\\nHaste Potion    1    19%\0
复制代码
我制作了一个类似字典的东西,也是一个txt,里面分左右两段,中间用逗号分开,逗号左边是要找的内容,逗号右边是要对应替换的内容。样式如下:
  1. \\nLeather Helmet Design    ,\\n测试皮头盔甲   
  2. \\nHaste Potion    ,\\n药水   
  3. \\nRecipe: Piece Bone Breastplate    ,\\n骨头胸甲的制作卷   
复制代码
注:为了保持格式正确且完全匹配,我在每个结尾都加了4个空格,因为源文本就有空格。

我希望能通过批处理执行后,源文本直接保持原格式替换,结果变为如下样式:
a,Recipe: Piece Bone Gaiters    1    59%\\n测试皮头盔甲    1    38%\\n骨头胸甲的制作卷    1    37%\0
a,Thread    2 - 3    100%\\nRecipe: Piece Bone Gaiters    1    59%\\n药水    1    19%\0

请大家帮帮忙,谢谢。
作者: czjt1234    时间: 2024-5-18 15:47

另存为 ANSI 编码的 vbs
  1. f1 = "text.txt"
  2. c1 = "GBK"       '文件编码,可以是 UTF-16 或 UTF-8
  3. f2 = "字典.txt"
  4. c2 = "GBK"
  5. Set oRegExp = CreateObject("VBScript.RegExp")
  6. oRegExp.Global = True
  7. oRegExp.IgnoreCase = True
  8. Set oStream1 = CreateObject("ADODB.Stream")
  9. oStream1.Type = 2
  10. oStream1.Mode = 3
  11. oStream1.Charset = c1
  12. oStream1.Open()
  13. oStream1.LoadFromFile f1
  14. s = oStream1.ReadText()
  15. Set oStream2 = CreateObject("ADODB.Stream")
  16. oStream2.Type = 2
  17. oStream2.Mode = 3
  18. oStream2.Charset = c2
  19. oStream2.Open()
  20. oStream2.LoadFromFile f2
  21. Do
  22.     m = oStream2.ReadText(-2)
  23.     If InStr(m, ",") Then
  24.         m = Split(m, ",", 2)
  25.         m(0) = RePlace(m(0), "\", "\\")
  26.         oRegExp.Pattern = m(0)
  27.         s = oRegExp.Replace(s, m(1))
  28.     End If
  29. Loop Until oStream2.EOS
  30. oStream1.Close()
  31. oStream1.Open()
  32. oStream1.WriteText s
  33. oStream1.SaveToFile f1, 2
  34. wsh.Echo "ok"
复制代码

作者: zhengwei007    时间: 2024-5-18 17:35

另存为 ANSI 编码的 vbs
czjt1234 发表于 2024-5-18 15:47


你好,我执行完后,text.txt文件里面有小方框,感觉像是编码不对。我已经把两个文件全部改成ANSI编码了还是不行。

文件我打包上传了,请您帮忙看下。谢谢。

链接: https://pan.baidu.com/s/1kLUnWvjviDh2ADWtva7VNQ 提取码: sisp 复制这段内容后打开百度网盘手机App,操作更方便哦
--来自百度网盘超级会员v9的分享
作者: czjt1234    时间: 2024-5-18 19:46

win7x64,下载测试正常,没发现有小方框
源文件编码就是GBK

vbs处理大文件还是不行,太慢,等第三方程序来看看吧
作者: 77七    时间: 2024-5-18 22:04

字典 2.txt源文件 1.txt
输出 3.txt
  1. @echo off
  2. cd /d "%~dp0"
  3. setlocal enabledelayedexpansion
  4. for /f "useback tokens=1-2 delims=,\" %%a in ("2.txt") do (
  5. set "str=%%~nxa"
  6. set "str=!str::= !"
  7. set "#"!str!"=%%~nxb"
  8. )
  9. (for /f "useback delims=" %%a in ("1.txt") do (
  10. set "str="%%a""
  11. set "str=!str:    =" "!"
  12. setlocal
  13. for %%b in (!str!) do (
  14. for /f "tokens=1* delims=\" %%c in ("%%~b") do (
  15. if "%%d" equ "" (
  16. set "x=!x!%%c    "
  17. ) else (
  18. set "d=%%d"
  19. set "d=!d::= !"
  20. if not defined #"!d!" (
  21. if "%%d" equ "0" (
  22. set "x=!x!%%c\%%d    "
  23. ) else (
  24. set "x=!x!%%c\\%%d    "
  25. )
  26. ) else (
  27. for /f "delims=" %%e in ("#"!d!"") do (
  28. set "x=!x!%%c\\!%%e!    "
  29. )
  30. )
  31. )
  32. )
  33. )
  34. echo !x:~0,-4!
  35. endlocal
  36. ))>3.txt
  37. endlocal
  38. pause
复制代码


如果字典也是几千行,代码效率低,不适用。如果有其它问题,请把源文件上传到网盘。
作者: 77七    时间: 2024-5-18 22:27

刚看到3楼,9000多行的字典,不知道超限制没,跑了五六分钟。结果 https://f.ws59.cn/f/e553x76waut
作者: zhengwei007    时间: 2024-5-19 00:32



你发的地址,打开后也有小方框。
我自己运行后的,也有小方框,还是编码不对?
作者: 77七    时间: 2024-5-19 01:03

回复 7# zhengwei007


   可能是软件原因,被错误识别了吧。换用其它的文本软件打开试试。
作者: Five66    时间: 2024-5-19 07:39

保存为gbk或ansi的bat
仅针对3楼内容的格式
源文本跟字典txt编码全部gbk/ansi
替换后会生成新文件,编码gbk/ansi
  1. @{}#? 2>nul&pause&powershell -c "gc -literalpath '%~f0'|out-string|iex"&exit/b
  2. [console]::writeline("`r`nrunning")
  3. #$thehash=new-object hashtable
  4. $thehash=@{}
  5. gc '字典.txt' |foreach{
  6. $str=$_ -split '    ,'
  7. if($thehash.ContainsKey($str[0])){
  8. $thehash[$str[0]]=$str[1].trimend()
  9. }else{
  10. $thehash.add($str[0],$str[1].trimend())
  11. }
  12. }
  13. gc 'text.txt' |foreach{
  14. $aaa=$_.replace('\\n','    \\n')
  15. $str=($aaa -split '    ' |foreach{if($thehash.ContainsKey($_)){$thehash[$_]}else{$_}}) -join '    '
  16. $str.replace('    \\n','\\n')
  17. } |sc the-new-text.txt
  18. [console]::writeline("`r`ndone")
  19. cmd /c pause
复制代码

作者: Five66    时间: 2024-5-19 07:40

回复 7# zhengwei007


    看右下角 , 编码被识别成 utf-8 了
作者: hfxiang    时间: 2024-5-19 15:20

本帖最后由 hfxiang 于 2024-5-24 10:32 编辑

回复 1# zhengwei007

命令行窗口下执行如下gawk(http://bcn.bathome.net/tool/4.1.0/gawk.exe)脚本可实现:
  1. gawk "FNR==NR{split($0, a, /[^,]+|(\042[^\042]+\042)/,m);r[m[1]]=m[2]}FNR<NR{split($0, a, /\\\\[^\\0-9]+    /,m);printf a[1];for(i in m){if(!r[m[i]])r[m[i]]=m[i];printf(\"%s%s\",r[m[i]],a[i+1])};print\"\"}" "字典.txt" "text.txt">"text_new.txt"
复制代码
效率也是杠杠的
(抱歉,原脚本有遗漏,现已修正)
作者: aloha20200628    时间: 2024-5-19 16:29

本帖最后由 aloha20200628 于 2024-5-19 18:38 编辑

回复 1# zhengwei007

用jscript和python两个版本分别测试了楼主提供的示例文件》text.txt(ansi编码), 字典.txt(ansi/gb2312编码)
前者用时约50秒,后者用时约20秒,测试系统硬件指标是intel i7-5500U
以下代码存为test.bat运行,生成替换结果文件为 text.new.txt(ansi/gb2312编码)
  1. @set @v=1 //&(cscript /e:jscript "%~f0")&exit/b
  2. //
  3. fso = new ActiveXObject('Scripting.FileSystemObject');
  4. fp = fso.OpenTextFile('字典.txt'), linesD = fp.readall().split('\r\n'), fp.close();
  5. fp = fso.OpenTextFile('text.txt'), lineT = fp.readall(), fp.close();
  6. fp = fso.OpenTextFile('text.new.txt',2,true);
  7. for (var kv,re,i=0,l=linesD.length; i<l; i++) {
  8. kv = linesD[i].split(','), k = trim(kv[0]), v = trim(kv[1]);
  9. eval('re=/'+k+'/gi;'), lineT = lineT.replace(re, v);
  10. }
  11. fp.write(lineT), fp.close(), WSH.quit();
  12. //
  13. function trim (s) { return s.replace(/(^\s*)|(\s*$)/g,''); }
复制代码
如果楼主已经预装了python系统,可将以下代码存为test.py,直接在命令行运行,生成替换结果文件为 text.new.txt(ansi/gb2312编码)
  1. #encoding=gbk
  2. import re
  3. with open('text.txt', 'r', -1) as fr:
  4. tLine = fr.read()
  5. with open('字典.txt', 'r', -1) as fr:
  6. dLines = fr.readlines()
  7. for d in dLines:
  8. kv = d.split(',')
  9. k, v = kv[0].strip(), kv[1].strip()
  10. tLine = re.sub(k, v, tLine, flags=re.I|re.S)
  11. with open('text.new.txt', 'w', -1) as fw:
  12. fw.write(tLine)
复制代码





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