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

[文本处理] 【已解决】如何用第三方工具,比较统计两文本的字符记录次数

本帖最后由 思想之翼 于 2024-12-3 16:45 编辑

D:\DATA\1.txt 记录字符:
中国 中国 中国 美国
欧盟 法国 法国 德国

D:\DATA\2.txt 记录字符:
中国 美国 美国
法国 法国 法国 法国
英国 德国

现在欲用第三方工具,比较统计上述两文本的字符记录次数。

分析上例:
中国:1.txt记录3次,2.txt记录1次
美国:1.txt记录1次,2.txt记录2次
欧盟:1.txt记录1次,2.txt记录0次
德国:1.txt记录1次,2.txt记录1次
英国:1.txt记录0次,2.txt记录1次
法国:1.txt记录2次,2.txt记录4次

1.txt 比 2.txt 记录次数多的字符为 中国 欧盟 ,写入D:\DATA\A.txt
2.txt 比 1.txt 记录次数多的字符为 美国 英国 法国,写入D:\DATA\B.txt
1.txt 与 2.txt 记录次数相同的字符为 德国,写入D:\DATA\C.txt

最终输出结果
A.txt
中国 欧盟

B.txt
美国 英国 法国

C.txt
德国


【注】下列代码,分别统计1.txt 与 2.txt的字符个数:
  1. gawk "{for(i=1;i<=NF;i++)a[$i]++}END{for(j in a)print j,a[j]}" 1.txt>统计1.txt
  2. gawk "{for(i=1;i<=NF;i++)a[$i]++}END{for(j in a)print j,a[j]}" 2.txt>统计2.txt
复制代码
结果:
统计1.txt
德国 1
美国 1
法国 2
欧盟 1
中国 3

统计2.txt
英国 1
德国 1
美国 2
法国 4
中国 1

不用第三方也可,有点文不对题:
  1. @echo off
  2. for /f "delims=" %%i in (1.txt) do (
  3.     for %%j in (%%i) do (
  4.         set _%%j=true
  5.         set /a @%%j+=1
  6.     )
  7. )
  8. for /f "delims=" %%i in (2.txt) do (
  9.     for %%j in (%%i) do (
  10.         set _%%j=true
  11.         set /a #%%j+=1
  12.     )
  13. )
  14. setlocal enabledelayedexpansion
  15. for /f "delims=_=" %%i in ('set _') do (
  16.     if not defined @%%i set @%%i=0
  17.     if not defined #%%i set #%%i=0
  18.     if !@%%i! gtr !#%%i! (
  19.         set a=!a!%%i
  20.     ) else if !@%%i! lss !#%%i! (
  21.         set b=!b!%%i
  22.     ) else (
  23.         set c=!c!%%i
  24.     )
  25. )
  26. for %%i in (a b c) do echo,!%%i!>%%i.txt
  27. pause
复制代码
权当自己练练手,这个就不要评分了。
1

评分人数

TOP

回复 1# 思想之翼

请确保1.txt及2.txt已以ansi编码保存,用gawk( http://bcn.bathome.net/tool/4.1.0/gawk.exe )在命令行窗口中实现方式如下:
  1. gawk -v"RS=\r?\n| " "{++a[$0][FILENAME];f[FILENAME]}END{PROCINFO[\"sorted_in\"]=\"@ind_str_desc\";for(i in a)for(j in f)if(!a[i][j]){};for(i in a){printf i;s=1;for(j in a[i]){sId=s?\":\":\",\";printf sId\" %s 记录 %d 次\",j,a[i][j];s=0}print\"\"}}" 1.txt 2.txt>3.txt
复制代码
如果1.txt及2.txt是以UTF-8编码保存,则可用RUBY( https://github.com/oneclick/ruby ... kit-3.3.6-2-x64.exe )中的gawk来处置
1

评分人数

TOP

本帖最后由 思想之翼 于 2024-12-3 14:58 编辑

回复 3# hfxiang
感谢!代码对比分析的中间结果正确,学习了。
1#表述重点不突出,所需的最终结果没有突出显示,以至让您疏忽了。

分析上例:
中国:1.txt记录3次,2.txt记录1次
美国:1.txt记录1次,2.txt记录2次
欧盟:1.txt记录1次,2.txt记录0次
德国:1.txt记录1次,2.txt记录1次
英国:1.txt记录0次,2.txt记录1次
法国:1.txt记录2次,2.txt记录4次

1.txt 比 2.txt 记录次数多的字符为 中国 欧盟 ,写入D:\DATA\A.txt
2.txt 比 1.txt 记录次数多的字符为 美国 英国 法国,写入D:\DATA\B.txt
1.txt 与 2.txt 记录次数相同的字符为 德国,写入D:\DATA\C.txt

最终输出结果
A.txt
中国 欧盟

B.txt
美国 英国 法国

C.txt
德国

TOP

本帖最后由 aloha20200628 于 2024-12-3 22:21 编辑

回复 1# 思想之翼

批处调用 findstr 可以拿下,代码量略多》先构建每个目标文件(d:\data\1.txt, d:\data\2.txt)对应的变量字典,再相互比对每本字典的键名及其键值,导出三个结果列表(a.txt, b.txt, c.txt)...
  1. @echo off &cd /d "d:\data" &del /q "a.txt", "b.txt", "c.txt" 2>nul
  2. setlocal &set "F1=1.txt" &set "F2=2.txt"
  3. (call :xx "%F1%") & (call :xx "%F2%")
  4. (for /f "delims=" %%a in ('findstr /vig:"_%F1%.0" "_%F2%.0" ') do set/p="%%a "<nul)>"b.txt"
  5. (for /f "delims=" %%a in ('findstr /vig:"_%F2%.0" "_%F1%.0" ') do set/p="%%a "<nul)>"a.txt"
  6. for /f "usebackq tokens=1,2 delims==" %%a in ("_%F1%.1") do (
  7.   for /f "tokens=1,2 delims==" %%x in ('findstr /lic:"%%~a" "_%F2%.1" ') do if %%b equ %%y (set/p="%%a "<nul>>"c.txt") else if %%b gtr %%y (set/p="%%a "<nul>>"a.txt") else (set/p="%%a "<nul>>"b.txt")
  8. )
  9. del/q "_%F1%.?" "_%F2%.?"&pause&exit/b
  10. :xx
  11.   setlocal enabledelayedexpansion
  12.   for /f "usebackq delims=" %%a in ("%~1") do for %%x in (%%a) do if defined _%%x (set/a "_%%x+=1") else (set "_%%x=1" &set "all=!all!,_%%x")
  13.   (for %%a in (!all!) do set "a=%%a"&echo,!a:~1!)>"_%~1.0"
  14.   (for %%a in (!all!) do set "a=%%a"&echo,!a:~1!=!%%a!)>"_%~1.1"
  15.   endlocal&exit/b
复制代码
1

评分人数

TOP

本帖最后由 hfxiang 于 2024-12-3 16:44 编辑

回复 4# 思想之翼
  1. gawk -v"RS=\r?\n| " "FNR==1{fn[++n]=FILENAME}{++a[$0][fn[n]]}END{for(i in a){if(a[i][fn[1]]>a[i][fn[2]]){printf\"%s \",i>\"A.txt\"}else if(a[i][fn[1]]<a[i][fn[2]]){printf\"%s \",i>\"B.txt\"}else{printf\"%s \",i>\"C.txt\"}}}" 1.txt 2.txt
复制代码
1

评分人数

TOP

  1. @echo off
  2. cd /d "D:\DATA\"
  3. if "%~1" equ "" (
  4. setlocal enabledelayedexpansion
  5. for /f "tokens=1-2" %%a in ('%0 # ^| sort ^& echo 1 1') do (
  6. if "!str!" neq "%%a" (
  7. if defined str (
  8. set /a m=#!str!
  9. if !m! gtr 0 (
  10. >>a.txt echo !str!
  11. ) else if !m! equ 0 (
  12. >>c.txt echo !str!
  13. ) else (
  14. >>b.txt echo !str!
  15. )
  16. )
  17. set str=%%a
  18. )
  19. set /a #!str!+=%%b
  20. )
  21. endlocal
  22. pause
  23. exit
  24. ) else (
  25. for %%i in ("1.txt|1" "2.txt|-1") do (
  26. for /f "tokens=1-2 delims=|" %%j in ("%%~i") do (
  27. for /f "useback delims=" %%a in ("%%j") do (
  28. for %%b in (%%a) do (
  29. echo %%b %%k
  30. )
  31. )
  32. )
  33. )
  34. )
复制代码
1

评分人数

bat小白,请多指教!谢谢!

TOP

本帖最后由 aloha20200628 于 2024-12-3 20:16 编辑

回复 1# 思想之翼

用5楼的算法复刻一个 bat+powershell 版本,以下代码存为 test.bat 运行,结果会在 d:\data 目录中产生 a.txt, b.txt, c.txt 三个文件...
  1. <# ::
  2. @echo off &cd /d "d:\data" &powershell "iex(${%~f0}|out-string)" &pause&exit/b
  3. #>
  4. $h1=@{}; gc 1.txt|%{foreach($i in $_.split()){if($h1.containsKey($i)){$h1[$i]+=1}else{$h1.add($i,1)}}}
  5. $h2=@{}; gc 2.txt|%{foreach($i in $_.split()){if($h2.containsKey($i)){$h2[$i]+=1}else{$h2.add($i,1)}}}
  6. $a=$b=$c=''; $h1.keys|%{if(!$h2.containsKey($_)){$a+=$_+' '}}; $h2.keys|%{if(!$h1.containsKey($_)){$b+=$_+' '}};
  7. $h1.keys|%{if($h2.containsKey($_)){if($h1[$_] -eq $h2[$_]){$c+=$_+' '}elseif($h1[$_] -gt $h2[$_]){$a+=$_+' '}else{$b+=$_+' '}}}
  8. sc a.txt $a.trimend(); sc b.txt $b.trimend(); sc c.txt $c.trimend(); exit
复制代码
1

评分人数

TOP

返回列表