Я работаю с хеш-таблицей, которую я создал, используя список из 3,5 миллионов IP-адресов, хранящихся в формате CSV, и я пытаюсь выполнить поиск в этой таблице с помощью подстановочных знаков.
CSV — это список IP-адресов MaxMind, который я конвертирую в Hashtable, используя следующий код.
[System.IO.File]::ReadLines("C:\temp\iptest.csv") | ForEach-Object { $data= $_.split(','); $ht = @{"geoname_id" = "$($data[1])";"registered_country_geoname_id" = "$($data[2])"}
$name = $($data[0])
$mainIPHhash.add($name, $ht)}
Код просто извлекает CIDR и соответствующий код города/страны. Это работает хорошо и создает таблицу чуть более чем за две минуты, но проблема, с которой я сейчас сталкиваюсь, заключается в поиске в этой хэш-таблице записей с подстановочными знаками.
Если я ищу полный CIDR, поиск происходит за миллисекунды.
$mainIPHhash.item("1.0.0.0/24")
Measure command reports - TotalSeconds : 0.0001542
Но если мне нужно выполнить поиск по подстановочным знакам, он должен пройтись по хеш-таблице в поисках моих похожих значений, что занимает много времени!
$testingIP = "1.0.*"
$mainIPHhash.GetEnumerator() | Where-Object { $_.key -like $testingIP }
Measure command reports - TotalSeconds : 33.3016279
Есть ли лучший способ поиска записей с подстановочными знаками в Hashtables?
Ваше здоровье
Редактировать:
Используя поиск по регулярному выражению, я могу сократить его до 19 секунд. Но все равно ужасно медленно
$findsStr = "^$(($testingIP2).split('.')[0])" +"\."+ "$(($testingIP2).split('.')[1])" +"\."
$mainIPHhash.GetEnumerator() | foreach {if ($_.Key -match $findsStr){#Dostuff }}
В приведенном выше примере берутся первые два октета IP-адреса и используется регулярное выражение для их поиска в хеш-таблице.
Days : 0
Hours : 0
Minutes : 0
Seconds : 19
Milliseconds : 733
Ticks : 197339339
TotalDays : 0.000228402012731481
TotalHours : 0.00548164830555556
TotalMinutes : 0.328898898333333
TotalSeconds : 19.7339339
TotalMilliseconds : 19733.9339
Вы можете взять список IP-адресов и сделать либо -like
, либо -match
для списка. Либо должно быть быстрее, чем предложение Where-Object
$mainIPhash.Values -like '1.0.*'
$mainIPhash.Values -match '^1\.0\.'
Что было быстрее? У меня действительно большой список со многими дубликатами.
Они хорошенькие на уровне! Вывод из команды измерения для первого - TotalMilliseconds: 0,1165. Второй - TotalMilliseconds: 0,1237
Другим решением может быть использование group-object :
$contentcsv=import-csv "C:\temp\iptest.csv" -Header Name, geoname_id, registered_country_geoname_id |Group Name
$contentcsv | where Name -like '1.0.*'
Спасибо! Единственная проблема заключается в том, что import-csv с таким большим файлом потребляет огромное количество ресурсов.
а ок, понял :)
Вы, сэр, легенда. Это сработало отлично. Спасибо.