Board logo

标题: [文本处理] 【已解决】BAT:如何合并前三列特定符号相同的行 [打印本页]

作者: 思想之翼    时间: 2022-11-25 21:36     标题: 【已解决】BAT:如何合并前三列特定符号相同的行

本帖最后由 思想之翼 于 2022-11-25 23:47 编辑

D:\DATA1\内有若干文本,编码为UTF-8,记录的数据格式如下:
A->
A->甲2
B->乙
B->乙2
C->丙
C->丙2
D->丁
D->丁2
E->戊
E->戊2
F->己
F->己2
G->庚
G->庚2
H->辛
H->辛2
I->壬
I->壬2
J->癸
J->癸2
甲乙丙丁戊己庚辛壬癸 表示的数字串 长短不一。

欲将数据整理成如下格式,编码UTF-8保持不变,写入D:\DATA2\
A->甲 甲2
B->乙 乙2
C->丙 丙2
D->丁 丁2
E->戊 戊2
F->己 己2
G->庚 庚2
H->辛 辛2
I->壬 壬2
J->癸 癸2
作者: WHY    时间: 2022-11-25 23:25

  1. <# :
  2. @echo off
  3. PowerShell -NoProfile -C ". ([ScriptBlock]::Create((gc -Literal '%~f0') -join \"`r`n\"))"
  4. pause & exit/b
  5. #>
  6. $path1 = 'D:\DATA1\';  #源目录
  7. $path2 = 'D:\DATA2\';  #目标目录
  8. if( -Not [IO.Directory]::Exists($path2) ){ $null = md $path2; }
  9. forEach( $file In (dir -Literal $path1 -Filter *.txt) ){
  10.     $dic = New-Object 'System.Collections.Generic.Dictionary[string, [Collections.ArrayList]]';
  11.     $res = [Collections.ArrayList]@();
  12.     forEach( $strLine In [IO.File]::ReadAllLines($file.FullName, [Text.Encoding]::UTF8) ){
  13.         $arr = $strLine -split '->';
  14.         if( $arr.Count -eq 2 ){
  15.             $key = $arr[0].ToLower();
  16.             if( -Not $dic.ContainsKey($key) ){
  17.                 $dic.Add( $key, @($strLine) );
  18.             }else{
  19.                 [void]$dic[$key].Add( $arr[1] );
  20.             }
  21.         }
  22.     }
  23.     forEach( $key In $dic.Keys ){
  24.         [void]$res.Add( $dic[$key] -join ' ' );
  25.     }
  26.     [IO.File]::WriteAllLines( $path2 + $file.Name, $res, [Text.Encoding]::UTF8 );
  27. }
复制代码

作者: hfxiang    时间: 2022-11-26 08:39

本帖最后由 hfxiang 于 2022-11-26 08:50 编辑

  1. A->甲
  2. A->甲2
  3. B->乙
  4. B->乙2
  5. C->丙
  6. C->丙2
  7. D->丁
  8. D->丁2
  9. E->戊
  10. E->戊2
  11. F->己
  12. F->己2
  13. G->庚
  14. G->庚2
  15. H->辛
  16. H->辛2
  17. I->壬
  18. I->壬2
  19. J->癸
  20. J->癸2
复制代码
以ANSI格式保存为1.txt
下载gawk( http://bcn.bathome.net/tool/4.1.0/gawk.exe
执行
  1. gawk -F"->" "{a[$1]=a[$1]?a[$1]\" \"$2:$2}END{for (id in a)print id FS a[id]}" 1.txt>2.txt
复制代码
结果(2.txt)
  1. A->甲 甲2
  2. B->乙 乙2
  3. C->丙 丙2
  4. D->丁 丁2
  5. E->戊 戊2
  6. F->己 己2
  7. G->庚 庚2
  8. H->辛 辛2
  9. I->壬 壬2
  10. J->癸 癸2
复制代码
补充:
把2.txt另存为UTF-8编码格式即可
或者使用Ruby中提供的GAWK,这个版本支持对UTF-8编码格式文本的操作
作者: terse    时间: 2022-11-26 08:50

这里用group也不错
  1. [IO.File]::ReadAllLines($file.FullName, [Text.Encoding]::UTF8)|
  2.     group { $_.split('->')[0]+'->' }|%{
  3.         $f = $_
  4.         $s = $($f.Group | % { $_.split('->')[-1] }) -join ' '
  5.         $f.Name + $s
  6. }
复制代码

作者: WHY    时间: 2022-11-26 14:36

本帖最后由 WHY 于 2022-11-26 23:55 编辑

Test.js
  1. var path1 = 'D:\\Data1\\';     //源文件路径
  2. var path2 = 'D:\\Data2\\';     //目标文件路径
  3. var getText = function(file){
  4.     var ado = new ActiveXObject('Adodb.Stream');
  5.     ado.Type = 2;
  6.     ado.CharSet = 'UTF-8';
  7.     ado.Open();
  8.     ado.LoadFromFile(file);
  9.     var text = ado.ReadText(-1);
  10.     ado.Close();
  11.     return text;
  12. }
  13. var saveFile = function(file){
  14.     var ado = new ActiveXObject('Adodb.Stream');
  15.     ado.Type = 2;
  16.     ado.CharSet = 'UTF-8';
  17.     ado.Open();
  18.     ado.WriteText(out.join('\r\n'));
  19.     ado.SaveToFile(file, 2);
  20.     ado.Close();
  21. }
  22. var fso = new ActiveXObject('Scripting.FileSystemObject');
  23. if( !fso.FolderExists(path2) ) fso.CreateFolder(path2);
  24. var e = new Enumerator( fso.GetFolder(path1).Files );
  25. var reg = /^((?:(?!->)\S)+)->(\S+)(?=\r\n|$)/mg;
  26. for(; !e.atEnd(); e.moveNext()){
  27.     if( !/\.txt$/i.test(e.item().Name) ) continue;
  28.     var map = {};
  29.     var out = [];
  30.     var str = getText( e.item().Path );
  31.     while( arr = reg.exec(str) ){
  32.         var key = arr[1].toLowerCase();
  33.         map[key] = map.hasOwnProperty(key) ? map[key] + ' ' + arr[2] : arr[0];
  34.     }
  35.     for( var key in map ) out.push(map[key]);
  36.     saveFile( path2 + e.item().Name );
  37. }
  38. WSH.Echo('Done');
复制代码

作者: WHY    时间: 2022-11-26 14:36

本帖最后由 WHY 于 2022-11-26 14:41 编辑
  1. @echo off
  2. md "D:\Data2\" 2>nul
  3. PowerShell "dir 'D:\Data1\' -Filter *.txt | forEach{(gc $_.FullName -Enc UTF8) -match '->' | group{($_ -split '->')[0]} | forEach{$_.Name + '->' + ($_.Group -replace '^(?:(?!->).)*->' -join ' ')} | sc ('D:\Data2\' + $_.Name) -Enc UTF8}"
  4. pause
复制代码

作者: 思想之翼    时间: 2023-2-21 15:15

本帖最后由 思想之翼 于 2023-2-21 15:30 编辑

回复 3# hfxiang
  1. gawk -F"->" "{a[$1]=a[$1]?a[$1]\" \"$2:$2}END{for (id in a)print id FS a[id]}" 1.txt>2.txt
复制代码
请教:gawk 合并后,各行如何分别实现删重效果
列如合并后:
A->甲 甲2 甲3 甲2,删重,保留1个甲2
B->乙 乙2 甲3 乙2,删重,保留1个乙2
......
结果:
A->甲 甲2 甲3
A->乙 乙2 乙3
......
作者: hfxiang    时间: 2023-2-21 15:29

回复 7# 思想之翼
  1. gawk -F"->" "!(($1 $2) in T) {T[$1 $2];a[$1]=a[$1]?a[$1]\" \"$2:$2}END{for (id in a)print id FS a[id]}" 1.txt>3.txt
复制代码

作者: 思想之翼    时间: 2023-2-21 15:36

本帖最后由 思想之翼 于 2023-2-21 15:38 编辑

谢谢您的帮助




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