标题: 【完结】50元求批处理——汉字信息提取 [打印本页]
作者: lxh623 时间: 2020-11-17 11:04 标题: 【完结】50元求批处理——汉字信息提取
本帖最后由 lxh623 于 2020-11-20 07:42 编辑
文本a是如下:
CB30597 [灬亠口├〡兀木]
方括号里面有些解析部件。有些可能有unicode码,有些没有。
文本IDS,如下:
U+24410 𤐐 ⿰火詹
文本dump,如下:
u6b0b | 99:0:0:2:0:160:200:u6728-01$99:0:0:59:0:197:200:dkw-23747@1
我的想法是:
把方括号里面的解析部件,从文本IDS提取unicode码,在文本dump搜索,同时含有所有的话,(没有unicode码的,忽略)把文本a那一行写入文本b,后面加上制表符+文本dump中制表符前面的内容。多个可能,就写几行。
文本IDS中的unicode码,我也可以处理到与文本dump一样。
所有文本编码是UTF8。
谢谢!
作者: zaqmlp 时间: 2020-11-17 11:22
举例说明下处理前后的效果并打包文件发网盘
作者: lxh623 时间: 2020-11-17 15:33
回复 2# zaqmlp
大致处理之后,上传了。dump想存UTF8,怎么也保存不了。
链接:https://pan.baidu.com/s/1pc2as9CPfpTwejYLwd1Vcw
提取码:q35z
谢谢!
作者: zaqmlp 时间: 2020-11-17 17:20
以这几个为例,最后结果是什么
CB17093 [、、]
CB32631 [亠二]
CB33987 [彡同]
CB29324 [忄日一]
作者: ivor 时间: 2020-11-17 20:11
我的想法是:
把方括号里面的解析部件,从文本IDS提取unicode码,在文本dump搜索,同时含有所有的话,(没有unicode码的,忽略)把文本a那一行写入文本b,后面加上制表符+文本dump中制表符前面的内容。多个可能,就写几行。
dump制表符前面存在重复,如果全部检索不能使用字典效率会很低。
作者: WHY 时间: 2020-11-17 20:18
本帖最后由 WHY 于 2020-11-17 20:25 编辑
PowerShell 脚本,保存为 E:\Test\大藏经解析\Test.ps1
运行方法:
1. 在cmd命令提示符下,输入 PowerShell -exec Bypass -file "E:\Test\大藏经解析\Test.ps1"
2.或者,右键单击脚本,选择"使用 PowerShell 运行"
试试吧。- $file1 = 'E:\Test\大藏经解析\IDS.txt';
- $file2 = 'E:\Test\大藏经解析\dump.txt';
- $file3 = 'E:\Test\大藏经解析\a.txt';
- $file4 = 'E:\Test\大藏经解析\b.txt';
-
- $hash1 = @{};
- $arr = [IO.File]::ReadAllLines($file1) -match '^u';
- $count = $arr.Count;
- for( $i=0; $i -lt $count; $i++ ){
- $m = $arr[$i].Trim() -split '\s+';
- if( !$hash1.ContainsKey($m[1]) ){ $hash1[$m[1]] = $m[0]; }
- }
-
- $hash2 = @{};
- $arr = [IO.File]::ReadAllLines($file2) -match '^u';
- $count = $arr.Count;
- for( $i=0; $i -lt $count; $i++ ){
- $m = $arr[$i].Trim() -split '\s+';
- if( !$hash2.ContainsKey($m[0]) ){ $hash2[$m[0]] = 1; }
- }
-
- $arr = [IO.File]::ReadAllLines($file3) -match '^CB';
- $count = $arr.Count;
- $out = for( $i=0; $i -lt $count; $i++ ){
- [char[]]$chs = ($arr[$i] -split '[\[\]]')[1]; #匹配中文字符
- [Collections.ArrayList]$a = @();
- for($j=0; $j -lt $chs.Count; $j++) {
- $s = '' + $chs[$j]; #char转string
- if( !$hash1.ContainsKey($s) ){ continue; }
- $key = $hash1[$s];
- if( $hash2.ContainsKey($key) ){ [void]$a.Add($key); }
- }
- if( $a.Count -eq $chs.Count ){
- $arr[$i] + "`t" + ($a -join "`t");
- }
- }
-
- [IO.File]::WriteAllLines($file4, $out);
- echo 'Done';
- [Console]::ReadKey();
复制代码
作者: lxh623 时间: 2020-11-18 08:22
本帖最后由 lxh623 于 2020-11-18 10:10 编辑
回复 6# WHY
CB33973 [十后] u5341 u540e
我的意思是在dump找到同时含有这两个或者几个Unicode码的行,把前面写到]+制表符后面。【这个例子好像没有】
发现一个问题,原件u3013开头的行,可以删除。
CB13270 [刂耳] u5202 u8033
这个有结果。但是,出来几个u205dc、u5235、u3013、u265ff、u350c、u8069。去掉u3013,还有五个。
所以,要是用以搜索的有n个unicode码,dump行里面就最好限定n+1个unicode码,可能更好。
或者,出来十个,都写上。自己再来删除重复。
结果样式:(这个都可以,都需要自己调整。)
CB13270 [刂耳] u5235
CB13270 [刂耳] 刵
谢谢!
作者: WHY 时间: 2020-11-18 20:21
本帖最后由 WHY 于 2020-11-19 10:38 编辑
回复 7# lxh623
这样的话,a.txt的每一行都要和dump.txt的每一行进行比较,行数太多,效率肯定不会高,你试试吧。- $file1 = 'E:\Test\大藏经解析\IDS.txt';
- $file2 = 'E:\Test\大藏经解析\dump.txt';
- $file3 = 'E:\Test\大藏经解析\a.txt';
- $file4 = 'E:\Test\大藏经解析\b.txt';
-
- #遍历 IDS.txt 每一行,加入字典
- $Dic1 = New-Object 'Collections.Generic.Dictionary[string, string]';
- $Dic3 = New-Object 'Collections.Generic.Dictionary[string, string]';
- $arr = [IO.File]::ReadAllLines($file1) -match '^u';
- $count = $arr.Count;
- for( $i=0; $i -lt $count; $i++ ){
- $a = $arr[$i].Trim().Split("`t ", 2, 'RemoveEmptyEntries'); #分割成2列
- if( !$Dic1.ContainsKey($a[1]) ){
- $Dic1.Add($a[1], $a[0]); #Dic1:key=第2列中文字符,value=第1列unicode码
- }
- if( !$Dic3.ContainsKey($a[0]) ){
- $Dic3.Add($a[0], $a[1]); #Dic3:key=第1列unicode码,value=第2列中文字符
- }
- }
-
- #遍历 dump.txt 每一行,加入字典
- $Dic2 = New-Object 'Collections.Generic.Dictionary[string, string]';
- $arr = [IO.File]::ReadAllLines($file2) -match '^u[0-9a-f]+\s+.*u[0-9a-f]+' -notMatch '^u3013\s'; #去掉u3013开头的行
- $count = $arr.Count;
- for( $i=0; $i -lt $count; $i++ ){
- $a = $arr[$i].Trim().Split("`t ", 2, 'RemoveEmptyEntries'); #分割成2列
- $k = forEach( $m In [regex]::Matches($a[1], '(?i)u[0-9a-f]+') ){
- $m.Groups[0].Value;
- }
- $key = $k -join ' ';
- if( !$Dic2.ContainsKey($key) ){
- $Dic2.Add($key, $a[0]); #Dic2:key=第2列的多个unicode码,value=第1列的unicode码
- }
- }
-
- #遍历 a.txt 每一行,如果在一行中同时匹配多个unicode码,写入b.txt
- $fsw = New-Object System.IO.StreamWriter($file4, $false, [Text.Encoding]::UTF8);
- $arr = [IO.File]::ReadAllLines($file3) -match '^CB';
- $count = $arr.Count;
- for( $i=0; $i -lt $count; $i++ ){
- [char[]]$chs = $arr[$i].Split('[]')[1]; #a.txt每一行的中文字符
- [Collections.ArrayList]$a = @();
- for( $j=0; $j -lt $chs.Count; $j++ ){
- $s = '' + $chs[$j]; #char转string
- if( $Dic1.ContainsKey($s) ){
- [void]$a.Add( '(?=.*' + $Dic1[$s] + '\b)' );
- } else { break; }
- }
- if( $a.Count -ne $chs.Count ){ continue; }
- $h = @{};
- $reg = $a -join ''; #正则,同时匹配多个字符串
- forEach( $key In ($Dic2.Keys -match $reg) ){
- if( !$h.ContainsKey($Dic2[$key]) ){
- $h[$Dic2[$key]] = 1; #哈希表赋值,用来去重复,key=Dump.txt的第一列
- }
- }
- if( $h.Count -eq 0 ){ continue; }
- $s = $h.Keys -join "`t";
- $s = [regex]::Replace($s, '\S+', {param($m); $m.Value + '-' + $Dic3[$m.Value]});
- echo( $arr[$i] + "`t" + $s );
- $fsw.WriteLine( $arr[$i] + "`t" + $s );
- $fsw.Flush();
- }
-
- $fsw.Dispose();
- echo 'Done';
- [Console]::ReadKey();
复制代码
作者: zaqmlp 时间: 2020-11-18 20:58
本帖最后由 zaqmlp 于 2020-11-19 13:52 编辑
bat- <# :
- cls
- @echo off
- cd /d "%~dp0"
- powershell -NoProfile -ExecutionPolicy bypass "Invoke-Command -ScriptBlock ([ScriptBlock]::Create([IO.File]::ReadAllText('%~f0',[Text.Encoding]::GetEncoding('GB2312')))) -Args '%~f0'"
- pause
- exit
- #>
- $file1=".\a.txt";
- $file2=".\IDS.txt";
- $file3=".\dump.txt";
- $file4=".\结果.txt";
-
- $self=get-item -liter $args[0];
- $path=$self.Directory.FullName;
- $file1=$file1 -replace '^\.',$path;
- $file2=$file2 -replace '^\.',$path;
- $file3=$file3 -replace '^\.',$path;
- $file4=$file4 -replace '^\.',$path;
- if(-not (test-path -liter $file1)){write-host ('"'+$file1+'" not found');exit;};
- if(-not (test-path -liter $file2)){write-host ('"'+$file2+'" not found');exit;};
- if(-not (test-path -liter $file3)){write-host ('"'+$file3+'" not found');exit;};
-
- $enc=[Text.Encoding]::UTF8;
- $text1=[IO.File]::ReadAllLines($file1, $enc);
- $text2=[IO.File]::ReadAllLines($file2, $enc);
- $text3=[IO.File]::ReadAllLines($file3, $enc);
-
- write-host 'Laoding……';
-
- $dic1=New-Object 'System.Collections.Generic.Dictionary[string,string]';
- $dic2=New-Object 'System.Collections.Generic.Dictionary[string,string]';
- for($i=0;$i -lt $text2.count;$i++){
- $line=$text2[$i].trim() -split '\s',2;
- if(-not $dic1.ContainsKey($line[1])){$dic1.add($line[1], $line[0])};
- if(-not $dic2.ContainsKey($line[0])){$dic2.add($line[0], $line[1])};
- };
-
- $dic3=New-Object 'System.Collections.Generic.Dictionary[string,object]';
- for($i=0;$i -lt $text3.count;$i++){
- $line=$text3[$i].trimstart() -split '\s',2;
- $m=[regex]::matches($line[1], '(?i)u[\da-f]+');
- if($m.count -ge 1){
- [System.Collections.ArrayList]$crr=@();
- foreach($k in $m){
- [void]$crr.add($k.groups[0].value);
- };
- $drr=@($crr|sort);
- $tmpline=$drr -join ':';
- if(-not $dic3.ContainsKey($tmpline)){
- [System.Collections.ArrayList]$key=@();
- $dic3.add($tmpline, $key);
- };
- if($dic3[$tmpline] -notcontains $line[0]){
- [void]$dic3[$tmpline].add($line[0]);
- };
- };
- };
-
- write-host 'Searching……';
-
- $fs=New-Object System.IO.FileStream($file4, [System.IO.FileMode]::Create);
- $sw=New-Object System.IO.StreamWriter($fs, $enc);
- for($i=0;$i -lt $text1.count;$i++){
- $line=$text1[$i].trim() -split '\s',2;
- $m=[regex]::matches($line[1].trim('[]'),'[\ud800-\udbff][\udc00-\udfff]|[\u0000-\uffff]');
- [System.Collections.ArrayList]$arr=@();
- if($m.count -ge 1){
- foreach($k in $m){
- if($dic1.ContainsKey($k.groups[0].value)){
- [void]$arr.add($dic1[$k.groups[0].value]);
- };
- };
- };
- $line=$text1[$i];
- if($arr.count -ge 1){
- $err=@($arr|sort);
- $tmpline=$err -join ':';$tmpline
- if($dic3.ContainsKey($tmpline)){
- for($j=0;$j -lt $dic3[$tmpline].count;$j++){
- if($dic2.ContainsKey($dic3[$tmpline][$j])){
- $line+=(' '+$dic3[$tmpline][$j]+'('+$dic2[$dic3[$tmpline][$j]]+')')
- };
- };
- };
- };
- write-host $line;
- $sw.WriteLine($line);
- $sw.Flush();
- };
- $sw.Close();
- $fs.Close();
复制代码
作者: lxh623 时间: 2020-11-19 10:24
很奇怪,有一个字,两位都没有找到。我手动筛选,找到了。
CB33086 [宀乙] 察
作者: lxh623 时间: 2020-11-19 10:24
帐结了,感谢两位。
作者: zaqmlp 时间: 2020-11-19 13:51
回复 10# lxh623
已修改
CB33086 [宀乙] u5be7(寧) u5bdf(察)
作者: WHY 时间: 2020-11-19 20:55
200多万行数的数据,经过筛选后117万多行,win10实测,正则匹配同时包含多个字符串的行没有for循环来的快。
思路同8楼,改成for循环。- $file1 = 'E:\Test\大藏经解析\IDS.txt';
- $file2 = 'E:\Test\大藏经解析\dump.txt';
- $file3 = 'E:\Test\大藏经解析\a.txt';
- $file4 = 'E:\Test\大藏经解析\b.txt';
-
- #遍历 IDS.txt 每一行,加入字典
- $Dic1 = New-Object 'Collections.Generic.Dictionary[string, string]';
- $Dic3 = New-Object 'Collections.Generic.Dictionary[string, string]';
- $arr = [IO.File]::ReadAllLines($file1) -match '^u';
- $count = $arr.Count;
- for( $i=0; $i -lt $count; $i++ ){
- $a = $arr[$i].Trim().Split("`t ", 2, 'RemoveEmptyEntries'); #分割成2列
- if( !$Dic1.ContainsKey($a[1]) ){
- $Dic1.Add($a[1], $a[0]); #Dic1:key=第2列中文字符,value=第1列unicode码
- }
- if( !$Dic3.ContainsKey($a[0]) ){
- $Dic3.Add($a[0], $a[1]); #Dic3:key=第1列unicode码,value=第2列中文字符
- }
- }
-
- #遍历 dump.txt 每一行,加入字典
- $Dic2 = New-Object 'Collections.Generic.Dictionary[string, string]';
- $arr = [IO.File]::ReadAllLines($file2) -match '^u[0-9a-f]+\s+.*u[0-9a-f]+' -notMatch '^u3013\s'; #去掉u3013开头的行
- $count = $arr.Count;
- for( $i=0; $i -lt $count; $i++ ){
- $a = $arr[$i].Trim().Split("`t ", 2, 'RemoveEmptyEntries'); #分割成2列
- $k = forEach( $m In [regex]::Matches($a[1], '(?i)u[0-9a-f]+') ){
- $m.Groups[0].Value;
- }
- $key = $k -join ' ';
- if( !$Dic2.ContainsKey($key) ){
- $Dic2.Add($key, $a[0]); #Dic2:key=第2列的多个unicode码,value=第1列的unicode码
- }
- }
-
- #遍历 a.txt 每一行,如果在一行中同时匹配多个unicode码,写入b.txt
- $fsw = New-Object System.IO.StreamWriter($file4, $false, [Text.Encoding]::UTF8);
- $arr = [IO.File]::ReadAllLines($file3) -match '^CB';
- $count = $arr.Count;
- for( $i=0; $i -lt $count; $i++ ){
- [char[]]$chs = $arr[$i].Split('[]')[1]; #a.txt每一行的中文字符
- [Collections.ArrayList]$a = @(); #数组a,存放中文字符对应的unicode码
- for( $j=0; $j -lt $chs.Count; $j++ ){
- $s = '' + $chs[$j]; #char转string
- if( $Dic1.ContainsKey($s) ){
- [void]$a.Add( $Dic1[$s] );
- } else { break; }
- }
- if( $a.Count -ne $chs.Count ){ continue; }
- $h = @{}; #哈希表,存放Dump.txt的第一列unicode码
- forEach( $key In $Dic2.Keys ){
- if( $h.ContainsKey($Dic2[$key]) ){ continue; }
- $flag = $true;
- for( $j=0; $j -lt $a.Count; $j++ ){
- if( $key.indexOf($a[$j]) -lt 0 ){
- $flag = $false;
- break;
- }
- }
- if( $flag ){ $h[$Dic2[$key]] = $true; }
- }
- if( $h.Count -eq 0 ){ continue; }
- $s = $h.Keys -join "`t";
- $s = [regex]::Replace($s, '\S+', {param($m); $m.Value + '-' + $Dic3[$m.Value]});
- echo( $arr[$i] + "`t" + $s );
- $fsw.WriteLine( $arr[$i] + "`t" + $s );
- $fsw.Flush();
- }
-
- $fsw.Dispose();
- echo 'Done';
- [Console]::ReadKey();
复制代码
作者: WHY 时间: 2020-11-21 15:44
仔细想想好像不对,8楼正则为啥比for循环还慢?
因为漏掉了一个限定符^,造成过度回溯。
46行改成:- [void]$a.Add( '(?=^.*' + $Dic1[$s] + '\b)' );
复制代码
终于正常了。MARK备查。
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |