Извините, за дополнительный ответ. Это необычно, но меня заинтриговал универсальный вопрос, и подход и информация моего первоначального ответа « с использованием -Like » совершенно разные. Кстати, если вы ищете положительный ответ на вопрос « Я считаю, что он должен существовать в. NET», чтобы принять ответ, вероятно, этого не произойдет, такой же квест существует для поиска StackOverflow в сочетании с C#
, .Net
или Linq
. В любом случае, тот факт, что никто не может найти команду single предположительно .Net
для этого до сих пор, вполне понятно, что вместо этого предлагаются несколько решений semi-.Net
, но я считаю, что это вызовет некоторые нежелательные накладные расходы для универсальной функции. Предполагая, что вы ByteArray (массив байтов, в котором выполняется поиск), и SearchArray (массив байтов для поиска) полностью случайны. Существует только 1/256 шанс, что каждый байт в ByteArray будет соответствовать первому байту SearchArray . В этом случае вам не нужно искать дальше, и если он совпадает с , вероятность того, что второй байт также совпадает, составляет 1/256 2 , et c. Это означает, что внутренний l oop будет работать только в 1,004 раз больше, чем внешний l oop. Другими словами, производительность всего, что находится за пределами внутреннего l oop (но во внешнем l oop), почти так же важно, как и то, что находится во внутреннем l oop! Обратите внимание, что это также означает, что вероятность того, что случайная последовательность размером 500 Кбайт существует в случайной последовательности 100 Мбайт, практически равна нулю. (Итак, насколько на самом деле случайны заданные вами двоичные последовательности? Если они далеки от случайности, я думаю, вам нужно добавить еще несколько деталей к своему вопросу). Худшим сценарием для моего предположения будет ByteArray , состоящий из тех же байтов (например, 0, 0, 0, ..., 0, 0, 0
), и SearchArray из тех же байтов, заканчивающийся другим байтом (например, 0, 0, 0, ..., 0, 0, 1
).
На основании этого он снова показывает (я также доказал это в некоторых других ответах), что собственные команды PowerShell не так уж плохи и, возможно, даже могут превзойти . Net / Linq
команд в некоторых случаях. В моем тестировании функция Find-Bytes
ниже примерно на 20% и вдвое быстрее, чем функция в вашем вопросе:
Find-Bytes
Возвращает индекс, где -Search
байт последовательность находится в последовательности байт -Bytes
. Если последовательность поиска не найдена, возвращается $Null
([System.Management.Automation.Internal.AutomationNull]::Value
).
Параметры
-Bytes
Массив байтов для поиска
-Search
Массив байтов для поиска
-Start
Определяет, где начать поиск в последовательности Bytes
(по умолчанию: 0
)
-All
По умолчанию будет возвращен только первый найденный индекс. Используйте переключатель -All
, чтобы получить оставшиеся индексы любых других найденных последовательностей поиска.
Function Find-Bytes([byte[]]$Bytes, [byte[]]$Search, [int]$Start, [Switch]$All) {
For ($Index = $Start; $Index -le $Bytes.Length - $Search.Length ; $Index++) {
For ($i = 0; $i -lt $Search.Length -and $Bytes[$Index + $i] -eq $Search[$i]; $i++) {}
If ($i -ge $Search.Length) {
$Index
If (!$All) { Return }
}
}
}
Пример использования:
$a = [byte[]]("the quick brown fox jumps over the lazy dog".ToCharArray())
$b = [byte[]]("the".ToCharArray())
Find-Bytes -all $a $b
0
31
Benchmark Обратите внимание, что вам следует открыть новый сеанс PowerShell, чтобы правильно протестировать это, поскольку Linq использует большой кеш, который должным образом не подходит для вашего варианта использования.
$a = [byte[]](&{ foreach ($i in (0..500Kb)) { Get-Random -Maximum 256 } })
$b = [byte[]](&{ foreach ($i in (0..500)) { Get-Random -Maximum 256 } })
Measure-Command {
$y = Find-Bytes $a $b
}
Measure-Command {
$x = posOfArrayWithinArray $b $a
}