Найти и заменить группу захвата внутри файла

0

Я пытаюсь прочитать текстовый файл, не важно, на каком языке ...

$x = [IO.File]::ReadAllText("__init__.py")

... найти строку

$pattern = [regex] '(?s)(?:ExportSTL.+?global_scale = .+?default=)(.+?),'

... и замените группу захвата ( (.+?)) другой строкой (например 10.0). Затем запишите в файл и закройте его.

Как я могу попасть в группу захвата таким образом, чтобы я мог изменить ее на месте и сохранить файл? Все мои попытки заменить всю согласованную линию на группу без захвата.

Лира
источник
Пожалуйста, прочитайте Могу ли я ответить на свой вопрос? и не отвечай в вопросе.
DavidPostill

Ответы:

1

Попробуйте создать позитивную группу за исключением группы без захвата:

$pattern = [regex] '(?s)(?<=ExportSTL.+?global_scale = .+?default=)(.+?),'

Требуется совпадение с группой lookbehind, но она не будет использовать никаких символов.

Строка замены будет просто '10.0'.

Менее экзотическим способом было бы превратить не захватывающую группу в нормальную группу:

$pattern = [regex] '(?s)(ExportSTL.+?global_scale = .+?default=)(.+?),'

Строка замены будет '${1}10.0'(с одинарными кавычками). The ${1}представляет первую группу. (Вам нужны фигурные скобки вокруг «1», чтобы он не попадал в «10.0».)

dangph
источник
Позитивный вид сзади не работает - взгляды должны быть нулевой ширины, поэтому квантификаторы не допускаются . Фигурные скобки ${1}работают, это то, чего мне не хватало.
Leeroy
@Leeroy, я считаю, что взгляды могут быть переменной ширины в PowerShell и .NET. Это правда, что они должны быть фиксированной ширины в некоторых других разновидностях регулярных выражений, таких как Boost (C ++).
dangph
Ой, извините, я вижу, что вы правы, поддержка вида с переменной шириной поддерживается. Я могу получить совпадение с вашим регулярным выражением, 1 --- 1.0и 0 --- 1.0,. Я не могу заставить его заменить, хотя. -replace $pattern, '10.0'изменяет все экземпляры default=something, вместо того , чтобы просто1.0
Leeroy
@ Leeroy, вот пример. Попробуйте выполнить это: '123abc' -replace '(?<=123)(abc)','xxx' он заменяет «abc» на «xxx». Если вы измените «123» в исходной строке, замена не произойдет. (Но в любом случае, я думаю, что второй способ с $1заменой, вероятно, лучше, потому что больше людей поймут это.)
dangph
0

Решение

Благодаря @dangph , вот сценарий с его предложением.

$x = [IO.File]::ReadAllText("__init__.py")
# Turned the non-capturing group into a normal group
$pattern = [regex] '(?s)(ExportSTL.+?global_scale = .+?default=)(.+?),'
# Put $1 in curly brackets, and added literal comma at end of replacement
$x -replace $pattern, '${1}10.0,' | Set-Content .\__init__.py

Обновленный Regex101

Лира
источник