Powershell:使用列表计算文件中字符串的实例

时间:2013-06-26 14:55:25

标签: windows unix powershell grep

我试图以“有效的方式”在“file2”中出现“file1”中的字符串(从40到400多个字符变化)的次数。 file1有大约2k行,file2有大约130k行。我目前有一个Unix解决方案在VM中约2分钟,在Cygwin约5个,但我试图用Powershell / Python做,因为文件在windows中我正在使用输出excel并使用自动化(AutoIT。)
我有一个解决方案,但它需要太长时间(与Cygwin完成的时间差不多 - 所有2k行 - 我在Powershell中只有40-50行!) 虽然我还没有准备解决方案,但如果有一个快速准确的解决方案,我也愿意使用Python。

这是Unix代码:

while read SEARCH_STRING; 
do printf "%s$" "${SEARCH_STRING}"; 
grep -Fc "${SEARCH_STRING}" file2.csv; 
done < file1.csv | tee -a output.txt;

这是我目前拥有的Powershell代码

$Target = Get-Content .\file1.csv
Foreach ($line in $Target){
    #Just to keep strings small, since I found that not all
    #strings were being compared correctly if they where 250+ chars
    $line = $line.Substring(0,180)
    $Coll = Get-Content .\file2.csv | Select-string -pattern "$line"
    $cnt = $Coll | measure
    $cnt.count
}

任何建议的想法都会有所帮助。

感谢。

修改

我正在尝试C.B.

建议的修改后的解决方案
del .\output.txt
$Target = Get-Content .\file1.csv
$file= [System.IO.File]::ReadAllText( "C:\temp\file2.csv" )
Foreach ($line in $Target){
    $line = [string]$line.Substring(0, $line.length/2)
    $cnt = [regex]::matches( [string]$file, $line).count  >> ".\output.txt" 
}

但是,由于我在file1中的字符串长度不同,我保持为SubString函数获取OutOfBound异常,所以我将输入字符串减半(/ 2)以尝试获得匹配。当我试图将它们减半时,如果我有一个开括号,它会告诉我:

Exception calling "Matches" with "2" argument(s): "parsing "CVE-2013-0796,04/02/2013,MFSA2013-35 SeaMonkey: WebGL
crash with Mesa graphics driver on Linux (C" - Not enough )'s."
At C:\temp\script_test.ps1:6 char:5
+     $cnt = [regex]::matches( [string]$file, $line).count  >> ".\output.txt ...
+     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ArgumentException

我不知道是否有办法提高powershell的输入限制(目前我的最大尺寸是406,但未来可能更大)或者只是放弃并尝试使用Python解决方案。

思想?

修改

感谢@ C.B.我得到了正确的答案,它完全符合Bash脚本的输出。以下是将结果输出到文本文件的完整代码:

$Target = Get-Content .\file1.csv
$file= [System.IO.File]::ReadAllText( "C:\temp\file2.csv" )
Foreach ($line in $Target){
    $cnt = [regex]::matches( $file, [regex]::escape($line)).count  >> ".\output.txt"    
}

2 个答案:

答案 0 :(得分:0)

尝试一下:

$Target = Get-Content .\file1.csv
$file= [System.IO.File]::ReadAllText( "c:\test\file2.csv" )
Foreach ($line in $Target){
    $line = $line.Substring(0,180)    
    $cnt = [regex]::matches( $file, [regex]::escape($line)).count    
}

答案 1 :(得分:0)

您的脚本存在的一个问题是,对于file2.csv中的每一行,您反复阅读file1.csv。只读一次文件并将内容存储在变量中应该可以大大加快速度。试试这个:

$f2 = Get-Content .\file2.csv

foreach ($line in (gc .\file1.csv)) {
  $line = $line.Substring(0,180)
  @($f2 | ? { $_ -match $line }).Count
}