发表文章

[最新] POWERSHELL 多线程在大数据文本中查找字符串

yhcfsr 1月前 0

问题:有个文件”SN12345678_古典名著.txt”,一个数据文本test.txt. test.txt的行内容格式大致如下:

"12345678","三国演义","罗贯中","200","人民出版社",

提取”SN12345678_古典名著.txt”中的8位数字,在test.txt中第一列(假设以逗号做为列的分隔符)进行比对,如果匹配成功,就将”SN12345678_古典名著.txt”重命名为”三国演义_12345678.txt”.

分析

如果逐行比对,如果test.txt有300W行,可能几个小时都出不了结果.

方案一

将test.txt读入变量,用正则对整个变量进行匹配,比逐行比对效率要高的多.

$content=[System.IO.File]::ReadAllLines('d:\test.txt',[text.encoding]::Default)
$content -match '12345678'

如果匹配成功,会列出所有匹配的内容,而不是布尔值.这样就可以提取结果中的内容.
然而,这个方案的效率还是不能让人满意.于是想到了多线程.

方案二

将test.txt的内容分割成N段,每段1W行,为每段建一个线程,共N个线程,每个线程单独进行匹配.可能逐行比对几个小时才能完成的任务,这个方案几十秒就完成了.

#============脚本块============
$ScriptBlock={
    Param([string]$file_name,[Object[]]$subcontent)
    $num_name=$file_name -replace '.*\\.*(\d{8}).*','$1';
    $ex_name=$file_name -replace '.*\\.*(\..*)','$1';

    [string]$str=($subcontent -match $num_name);
    if($str -ne ''){
        $var=$str.Split(',').Trim('"');
        $new_name=$var[1]+'_'+$var[0]+$ex_name;
        Rename-Item -Path $file_name -NewName  $new_name -Force;
    }
}
#============创建缓存区============
$sessionState = [System.Management.Automation.Runspaces.InitialSessionState]::CreateDefault();
$sessionstate.Variables.Add((New-Object -TypeName System.Management.Automation.Runspaces.SessionStateVariableEntry -ArgumentList "myString" ,$myString, "example string"));   
$RunspacePool = [RunspaceFactory]::CreateRunspacePool(1, 1000, $sessionState, $Host);
$RunspacePool.Open();
[System.Collections.ArrayList]$Jobs=@();

#============读取数据文本============
$content=[System.IO.File]::ReadAllLines('d:\test.txt',[text.encoding]::Default);
$count=$content.count;
$LEN,$start,$end=10000,0,0;
[system.Collections.ArrayList]$TmpContent=@();
#============分割数据文本============
do{
    $end=[math]::Min($count,$start+$LEN);
    $end-=1;
    $null=$TmpContent.Add($content[$start..$end]);#将数据段保存到数组列表
    $end+=1;
    $start=$end;
}while($end -lt $count)
#============创建多线程============
do{
    $FileName=Read-Host -Prompt '将文件拖入这里';
    $FileName=$FileName -replace'"','';
    foreach($element in $TmpContent){
        $Job = [powershell]::Create().AddScript($ScriptBlock).AddArgument($FileName).AddArgument($element);
        $Job.RunspacePool = $RunspacePool;
        $null=$Job.BeginInvoke();
    }
}while($FileName -ne '')
相关推荐
最新评论 (0)
返回
发表文章
yhcfsr
文章数
8
评论数
0
注册排名
1012364