Powershell заменяет символы в позиции x - PullRequest
0 голосов
/ 07 июня 2019
Powershell 5.x

Есть строка $s, длиной примерно 2,5 КБ.Мне нужно выполнить серию замен (около 20) на нем, в цикле.Всего есть несколько 800K строк, поэтому мне нужно, чтобы это было fast .Для каждой замены я знаю позицию [int] $x и новое значение [string] $ns.

. Пример: мы начинаем с $s == "abcdefghijklmn", а $x (position) равен 3, а новое значение, которое нужно поставить, равно $ns == "XYZ"В итоге получаем $s == "abcXYZghijklmn" (строки индексируются на основе 0)

Мое решение на данный момент:

$s = "abcdefghijklmn"
$ns = "XYZ"
$x = 3
$s = $s.Remove($x, $ns.Length).Insert($x, $ns)

Это как минимум три операции: удаление строки, затем вставкановая строка и, наконец, сохранение конечного результата (не уверен насчет внутренних функций здесь, но я предполагаю, что так все и работает).Для строк по 800 КБ по 2,5 КБ каждая мы говорим о ~ 2 ГБ данных, обрабатываемых три раз в памяти.Это не самый эффективный способ работы.

В Python, с MutableString, я могу выполнять замену на месте с минимальными затратами.Существует ли подобное в Powershell?

Ответы [ 4 ]

1 голос
/ 07 июня 2019

Вот мой пример использования класса Stringbuilder.

$s = "abcdefghijklmn" -as [system.text.stringbuilder]
$ns = "XYZ"
$x = 3

$s.Replace($s.tostring().substring($x,$ns.length),$ns,$x,$ns.length).tostring()
0 голосов
/ 07 июня 2019

Это должно быть быстрее. Вы должны преобразовать входную строку в массив символов один раз перед заменами и преобразовать ее обратно в строку после завершения всех замен:

$s  = ("abcdefghijklmn").ToCharArray()
$ns = ("XYZ").ToCharArray()
$x  = 3
0..($ns.Length-1) | ForEach-Object { $s[$x + $_] = $ns[$_] }

$result = [String]::new($s)
0 голосов
/ 07 июня 2019

Вот еще одна альтернатива. Использует регулярное выражение.

$s  = "abcdefghijklmn"
$ns = "XYZ"
$x  = 3

$s -replace "(?m)^(.{$x}).(.+)", "`$1$ns`$2"

Детали регулярного выражения:

    ^       Assert position at the beginning of a line (at beginning of the string or after a line break character)
(           Match the regular expression below and capture its match into backreference number 1
   .        Match any single character that is not a line break character
      {3}   Exactly 3 times
)
.           Match any single character that is not a line break character
(           Match the regular expression below and capture its match into backreference number 2
   .        Match any single character that is not a line break character
      +     Between one and unlimited times, as many times as possible, giving back as needed (greedy)
)

Вы должны сами проверить, какое из предложенных решений является самым быстрым в вашей ситуации.

0 голосов
/ 07 июня 2019

Как насчет восстановления строки?

$s.Substring(0,$x) + $ns + $s.Substring($x)

Не уверен, что это быстрее, возможно, стоит проверить все строки, которые у вас есть. Вы также можете запускать вещи параллельно с foreach, чтобы ускорить процесс.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...