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

[文本处理] 求助批处理从一堆文本文件中提取关键词写到csv中

本帖最后由 zhengwei007 于 2023-12-14 10:45 编辑

我想从100多个文档里面,发现有Soul Crystal字符时,截取下面一行的ID 4645,和最后一行的4682,单独存放在csv文件里。
文档中是以<item>开头,</item>结尾的,谢谢大家。
由于不能上传附件,我粘点里面内容吧。
  1. <item>
  2. <!-- Stormbringer -->
  3. <ingredient count="1" id="72" />
  4. <!-- Red Soul Crystal - Stage 5 -->
  5. <ingredient count="1" id="4634" />
  6. <!-- Gemstone C -->
  7. <ingredient count="97" id="2131" />
  8. <!-- Adena -->
  9. <ingredient count="291000" id="57" />
  10. <!-- Stormbringer - Critical Anger -->
  11. <production count="1" id="4681" />
  12. </item>
  13. <item>
  14. <!-- Stormbringer -->
  15. <ingredient count="1" id="72" />
  16. <!-- Green Soul Crystal - Stage 5 -->
  17. <ingredient count="1" id="4645" />
  18. <!-- Gemstone C -->
  19. <ingredient count="97" id="2131" />
  20. <!-- Adena -->
  21. <ingredient count="291000" id="57" />
  22. <!-- Stormbringer - Focus -->
  23. <production count="1" id="4682" />
  24. </item>
复制代码
从这里提取4634和4681即可,每个文件里可能有多个这样的内容结构。
最终csv就是这样:
4634,4681
4645,4682

链接:https://pan.baidu.com/s/13ecRnqY4tPRaoFcVBEBLTg
提取码:xlit
这里存放了几个真实的文本文件的下载地址。

回复 1# zhengwei007


    请选择其中3个文件打包压缩上传到网盘我试试
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

链接:https://pan.baidu.com/s/13ecRnqY4tPRaoFcVBEBLTg
提取码:xlit
--来自百度网盘超级会员V9的分享

谢谢管理。

TOP

回复 3# zhengwei007


    请编辑一下顶楼的帖子,把下载链接放进去,方便他人看到。
我帮忙写的代码不需要付钱。如果一定要给,请在微信群或QQ群发给大家吧。
【微信公众号、微信群、QQ群】http://bbs.bathome.net/thread-3473-1-1.html
【支持批处理之家,加入VIP会员!】http://bbs.bathome.net/thread-67716-1-1.html

TOP

回复  zhengwei007


    请编辑一下顶楼的帖子,把下载链接放进去,方便他人看到。
Batcher 发表于 2023-12-14 10:37



   
好的,已经编辑完成。

TOP

用的busybox的sh,这东西可以打包成exe,写的丑了点
  1. for f in *.xml; do awk -v RS='</item>' -F '\n' '/Soul Crystal/{for(i=1;i<=NF;i++){if($i~/Soul Crystal/){gsub(".*id=\"|\".*","",$(i+1));gsub(".*id=\"|\".*","",$(NF-1));print $(i+1)","$(NF-1)}}}' "$f" > "$f.csv"; done
复制代码

TOP

用的busybox的sh,这东西可以打包成exe,写的丑了点
wanghan519 发表于 2023-12-14 12:52



可以做成批处理文件吗?.bat后缀,我可以直接执行的那种。我这没有linux,谢谢!

TOP

回复 7# zhengwei007


    呃,bat处理引号我是真不会。。。
可以下个busybox-w32执行,也就0.5M,提供sh环境包括awk,且可以把脚本编译成exe,很方便的小工具

TOP

回复  zhengwei007


    呃,bat处理引号我是真不会。。。
可以下个busybox-w32执行,也就0.5M,提供 ...
wanghan519 发表于 2023-12-14 14:07



你好,我试过了,可能有一点没说清楚,是所有数据全部汇总到一个csv下,不是单独的csv文件。随便起个名字,data.csv就行。

TOP


测试文件名假设为 test.xml
获取结果文件名为 test.csv
如下代码存为批处理脚本文件(test.cmd 或 test.bat)
楼主提供的样本已测试通过。
  1. @echo off &setlocal enabledelayedexpansion
  2. findstr /inc:"Soul Crystal" /inc:"</item>" "test.xml" 2>nul>tmp.0
  3. (for /f "tokens=1 delims=:" %%k in (tmp.0) do (
  4. if not defined v1 (call :getV "test.xml" %%k v1) else (
  5. set/a "n=%%k-2"
  6. (call :getV "test.xml" !n! v2)
  7. echo,!v1!,!v2!
  8. set "v1="
  9. )
  10. ))>"test.csv"
  11. del /q tmp.0
  12. endlocal &pause &exit/b
  13. :getV //%1=文件名 %2=行号 %3=返回值变量名
  14. for /f "usebackq skip=%~2 delims=" %%s in ("%~1") do (
  15. for /f tokens^=1-4^delims^=^" %%1 in ("%%~s") do (set "%~3=%%4")
  16. exit/b
  17. ) & exit/b
复制代码

TOP

谢谢6楼和10楼的兄弟,问题已经全部解决。

TOP

  1. @echo off
  2. cd /d "%~dp0"
  3. (for %%i in (*.xml) do (
  4. setlocal
  5. for /f "useback delims=" %%a in ("%%i") do (
  6. set str=%%a
  7. setlocal enabledelayedexpansion
  8. set "str1=!str:Soul Crystal=!"
  9. set "str2=!str: </item>=!"
  10. if "!str!" neq "!str1!" (
  11. endlocal
  12. set m=1
  13. ) else if defined m (
  14. endlocal
  15. for /f tokens^=4delims^=^" %%x in ("%%a") do (
  16. set n=%%x
  17. )
  18. set m=
  19. ) else if "!str!" neq "!str2!" (
  20. endlocal
  21. if defined n (
  22. setlocal enabledelayedexpansion
  23. for /f tokens^=4delims^=^" %%x in ("!_str!") do (
  24. echo !n!,%%x
  25. )
  26. endlocal
  27. set n=
  28. )
  29. ) else (
  30. endlocal
  31. )
  32. set _str=%%a
  33. )
  34. endlocal
  35. ))>data.csv
  36. pause
复制代码
bat小白,请多指教!谢谢!

TOP

回复 1# zhengwei007

假设所有xml文件均在同1个文件夹下,用第3方工具gaw( http://bcn.bathome.net/tool/5.1.0/gawk.exe ),在命令行方式下,其实现方法如下:
  1. awk -v"OFS=," "/^\t+<item>$/,/^\t+<\/item>$/{if(/Soul Crystal/)exist_id=1;if(/^\t+<ingredient count=\"1\" id=\"[0-9]+\" \/>$/)if(exist_id)A=gensub(/^\t+<ingredient count=\"1\" id=\"([0-9]+)\" \/>$/,\"\\1\",\"g\",$0);if(/^\t+<production count=\"1\" id=\"[0-9]+\" \/>$/)if(exist_id)print A,gensub(/^\t+<production count=\"1\" id=\"([0-9]+)\" \/>$/,\"\\1\",\"g\",$0);if(/^\t+<\/item>$/)exist_id=0}" *.xml>out.csv
复制代码

TOP

本帖最后由 WHY 于 2023-12-17 23:02 编辑
  1. @if(0)==(0) echo off
  2. dir /b *.xml | cscript -nologo -e:jscript "%~f0" > result.csv
  3. pause & exit
  4. @end
  5. var fso = new ActiveXObject('Scripting.FileSystemObject');
  6. while(!WSH.StdIn.AtEndOfStream) {
  7.     var f = WSH.StdIn.ReadLine();
  8.     var s = fso.OpenTextfile(f, 1).ReadAll();
  9.     var m = s.match(/<item>(?:(?!<\/?item>)[\s\S])+<\/item>/g);
  10.     for(var i=0; i<m.length; i++) {
  11.         var m1 = m[i].match(/\bSoul Crystal\b.+\n(?:(?!\bid=).)+\bid="([^"]+)"/);
  12.         var m2 = m[i].match(/\bproduction\b(?:(?!\bid=).)+\bid="([^"]+)"/);
  13.         if(m1 && m2) WSH.Echo(m1[1] + ',' + m2[1]);
  14.     }
  15. }
复制代码
  1. @if(0)==(0) echo off
  2. dir /b *.xml | cscript -nologo -e:jscript "%~f0" > result.csv
  3. pause & exit
  4. @end
  5. var xml = new ActiveXObject('Microsoft.XMLDOM');
  6. var reg = /\bSoul Crystal\b/;
  7. while(!WSH.StdIn.AtEndOfStream) {
  8.     var f = WSH.StdIn.ReadLine();
  9.     getXmlData(f);
  10. }
  11. function getXmlData(fileName) {
  12.     xml.load(fileName);
  13.     var nodes = xml.selectNodes('//item');
  14.     for(var i=0; i<nodes.length; i++) {
  15.         var s2 = nodes[i].lastChild.getAttribute('id');
  16.         var childs = nodes[i].childNodes;
  17.         for(var j=0; j<childs.length; j++) {
  18.             if(childs[j].nodeName == '#comment' && reg.test(childs[j].text)) {
  19.                 var s1 = childs[j+1].getAttribute('id');
  20.                 WSH.Echo(s1 + ',' + s2);
  21.                 break;
  22.             }
  23.         }
  24.     }
  25. }
复制代码

TOP

这样行不?
  1. @echo off&chcp 936
  2. echo 进行中,请耐心等待
  3. set "outfile=___output.csv"
  4. cd.>"%outfile%"
  5. for %%b in ("*.xml") do (
  6. setlocal
  7. echo,file,%%~b>>%outfile%
  8. (for /f "skip=1 delims=" %%c in ('findstr /n .* "%%~b"') do (
  9. set line1=
  10. set /p line1=
  11. set line2=%%c
  12. if not defined item (
  13. setlocal enabledelayedexpansion
  14. if "!line1:<item>=!" neq "!line1!" (
  15. for %%- in (1) do endlocal&set item=%%-) else endlocal
  16. ) else (
  17. setlocal enabledelayedexpansion
  18. if "!line1:Soul Crystal=!" neq "!line1!" (
  19. set line3=!line2:* =!&set line3=!line3:~0,-2!
  20. 2>nul set /a !line3:id=,id!
  21. for %%- in ("!id!") do endlocal&set o=%%~-&set match=1
  22. if "!p!" == "!q!" endlocal
  23. ) else endlocal
  24. if defined match (
  25. setlocal enabledelayedexpansion
  26. if "!line2:</item>=!" neq "!line2!" (
  27. set line3=!line1:* =!&set line3=!line3:~0,-2!
  28. 2>nul set /a !line3:id=,id!
  29. echo,!o!,!id!
  30. endlocal&set o=&set match=&set item=
  31. ) else endlocal
  32. )
  33. )
  34. ))<"%%~b">>"%outfile%"
  35. endlocal
  36. )
  37. echo,&echo 完成&pause
复制代码

TOP

返回列表