返回列表 发帖

【完结】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。

谢谢!

举例说明下处理前后的效果并打包文件发网盘
提供bat代写,为你省时省力省事,支付宝扫码头像支付
微信: unique2random

TOP

回复 2# zaqmlp
大致处理之后,上传了。dump想存UTF8,怎么也保存不了。
链接:https://pan.baidu.com/s/1pc2as9CPfpTwejYLwd1Vcw
提取码:q35z

谢谢!

TOP

以这几个为例,最后结果是什么
CB17093        [、、]
CB32631        [亠二]
CB33987        [彡同]
CB29324        [忄日一]
提供bat代写,为你省时省力省事,支付宝扫码头像支付
微信: unique2random

TOP

我的想法是:
把方括号里面的解析部件,从文本IDS提取unicode码,在文本dump搜索,同时含有所有的话,(没有unicode码的,忽略)把文本a那一行写入文本b,后面加上制表符+文本dump中制表符前面的内容。多个可能,就写几行。

dump制表符前面存在重复,如果全部检索不能使用字典效率会很低。
#&cls&@powershell "Invoke-Expression ([Io.File]::ReadAllText('%~0',[Text.Encoding]::UTF8))" &pause&exit

TOP

本帖最后由 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();COPY
1

评分人数

TOP

本帖最后由 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        [刂耳]        刵

谢谢!

TOP

本帖最后由 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();COPY
1

评分人数

TOP

本帖最后由 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();COPY
1

评分人数

提供bat代写,为你省时省力省事,支付宝扫码头像支付
微信: unique2random

TOP

很奇怪,有一个字,两位都没有找到。我手动筛选,找到了。
CB33086        [宀乙] 察

TOP

帐结了,感谢两位。

TOP

回复 10# lxh623
已修改
CB33086 [宀乙] u5be7(寧) u5bdf(察)
提供bat代写,为你省时省力省事,支付宝扫码头像支付
微信: unique2random

TOP

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();COPY
1

评分人数

TOP

仔细想想好像不对,8楼正则为啥比for循环还慢?
因为漏掉了一个限定符^,造成过度回溯。
46行改成:
[void]$a.Add( '(?=^.*' + $Dic1[$s] + '\b)' );COPY
终于正常了。MARK备查。

TOP

返回列表