Массовое удаление регулярных выражений для большого массива очень медленно в PowerShell - PullRequest
0 голосов
/ 25 июня 2018

Я пытаюсь найти самый быстрый / эффективный способ запуска множества удалений регулярных выражений для массива.

Мой массив $hosts содержит десятки тысяч отдельных элементов в формате домена.Например:

  • test.domain.xyz

  • domain.xyz

  • thing.com

  • anotherdomain.net

My $local_regex массив содержит ~ 1000 отдельных регулярных выражений в многострочном формате.Например:

  • ^ ad.(ad. *)

  • domain.xyz $ (* domain.xyz)

В настоящее время я пытаюсь исключить любые совпадения регулярных выражений вследующим образом, но это ОЧЕНЬ медленно с большим массивом и множеством подходящих регулярных выражений:

Function Regex-Remove
{
    Param
    (
        [Parameter(Mandatory=$true)]
        $local_regex,
        [Parameter(Mandatory=$true)]
        $hosts
    )

    # Loop through each regex and select only non-matching items
    foreach($regex in $local_regex)
    {
        # Multi line, case insensitive
        $regex = "(?im)$regex"

        # Select hosts that do not match regex
        $hosts = $hosts -notmatch $regex
    }

    return $hosts
}

Есть ли лучший способ сделать это?

Ответы [ 3 ]

0 голосов
/ 25 июня 2018

Вы можете использовать объекты System.Collections.ArrayList вместо массивов, это значительно ускорит процесс, и у вас есть методы для добавления / удаления элементов без перестройки всего массива

$var = New-Object System.Collections.ArrayList

$var.Add()
$var.AddRange()
$var.Remove()
$var.RemoveRange()
0 голосов
/ 25 июня 2018

Как подсказал @Roberto, я переключил массив $hosts на New-Object System.Collections.ArrayList

Возможность удаления из ArrayList на лету - это как раз то, что мне нужно, а цикл while обязательно удаляет повторяющиеся значения.

Function Regex-Remove
{
    Param
    (
        [Parameter(Mandatory=$true)]
        $local_regex,
        [Parameter(Mandatory=$true)]
        $hosts
    )

    # Loop through each regex and select only non-matching items
    foreach($regex in $local_regex)
    {
        # Multi line, case insensitive
        $regex = "(?i)$regex"

        # Select hosts that do not match regex
        $hosts -match $regex | % {
            while($hosts.Contains($_))
            {
                $hosts.Remove($_)
            }
        }
    }

    return $hosts
}
0 голосов
/ 25 июня 2018

Переназначение большого массива будет дорогостоящим. Изменение размера массива требует выделения нового массива и копирования содержимого в него. Например, если у вас есть 10 000 имен хостов и 1 000 регулярных выражений, у вас есть 10 000 000 операций копирования. Это будет иметь некоторый ощутимый эффект. Существует командлет Measure-Command, который используется для определения времени выполнения.

В качестве альтернативного подхода попробуйте использовать индексированный массив и перезаписать нежелательные значения значениями $null. Вот так

foreach($regex in $local_regex) {
    $regex = "(?im)$regex"
    for($i=0;$i -lt $hosts.length; ++$i) {
        if( $hosts[$i] -match $regex) {
            $hosts[$i] = $null
        }
    }
}
...