我有两个文件,file1
和file2
。我需要检查file1
中是否存在file2
中的所有内容。 file1
的内容如下:
ABC1234 BFD7890
file2
的内容如下:
ABC1234_20180902_XYZ BFD7890_20110890_123
它们不会以任何特定的顺序排列,并且不可能通过分隔符进行拆分,因为它们在不同的行中是不同的。我需要确认的是,如果来自file1
的字符串存在于file2
的某些部分。不会出现两次相同的模式。
两个文件都包含20000多行。
这就是我目前拥有的:
$filesfromDB = gc file1.txt
$filesfromSFTP = gc file2.txt
foreach ($f in $filesfromDB) {
$FilePresentStatus = $filesfromSFTP | Select-String -Quiet -Pattern $f
if ($FilePresentStatus -ne $true) {
$MissingFiles += $f
}
}
如果文件很小,这可以正常工作,但是当我在prod中运行它时,它确实很慢。完成此循环大约需要4个小时。如何优化这段脚本?
20000并不是那么多,但最糟糕的是你必须做20000x20000 = 400000000次操作。关键是要尽快停止。你也可以使用更快的[string].Contains
方法而不是基于正则表达式的Select-String
(除非使用-SimpleMatch开关)。
见以下演示:
$db = 1000000..1020000
$sftp = (1001000..1021000 | % { "$($_)_SomeNotImportantTextHere" }) -join "`r`n"
$missingFiles = $db | where { !$sftp.Contains($_) }
每个集合包含20000个项目,19000个常见,1000个仅存在于$db
。它运行几秒钟。
要将$filesfromSFTP
读作一个大字符串,请使用:
gc file2.txt -Raw
要将结果转换为单个字符串,请使用$missingFiles -join 'separator'
。
使用哈希表,下面的代码在我的笔记本电脑上大约需要15分钟,其中2个文件包含20000行。
$filesfromDB = gc file1.txt
$filesfromSFTP = gc file2.txt
$MissingFiles = @()
$hashtbl = @{}
foreach ($f in $filesfromDB) {
$hashtbl."Line$($f.ReadCount)"=[regex]$f
}
foreach ($key in $hashtbl.Keys) {
$FilePresentStatus = $hashtbl[$key].Matches($filesfromSFTP)
if ($FilePresentStatus.Count -eq 0) {
$MissingFiles += $hashtbl[$key].ToString()
}
}