Замена регулярного выражения: строки для вызова функции

Мой скрипт AutoIt содержит множество строк. Например :

;This is AutoIt
$string1 = "This is a test string" & @crlf & "Wow, autoit syntax!"$string2 = "This string has a var. Var1=" & $var1
$wow = random_function("Another string") & "this is getting complex"magic_function("var1=" & $var1 & @crlf & "other var=" & $var2)
$multivar = "This string has 2 vars: var1=" & $var1 & " var2=" $var2"

Я хочу заменить каждую строку вызовом функции. Таким образом, приведенный выше скрипт станет:

;This is AutoIt
$string1 = get_string(1) & @crlf & get_string(2)
$string2 = get_string(3,$var1)
$wow = random_function(get_string(4)) & get_string(5)
magic_function(get_string(6,$var1) & @crlf & get_string(7,$var2))
$multivar = get_string(8,$var1,$var2)

ИЛИ ЖЕ

;This is AutoIt
$string1 = get_string(1,@crlf)
$string2 = get_string(3,$var1)
$wow = random_function(get_string(4)) & get_string(5)
magic_function(get_string(6,$var1,@crlf,$var2))
$multivar = get_string(8,$var1,$var2)

Оба хороши для меня. Я ищу решение регулярных выражений. Скрипты содержат строки, которые не должны быть заменены, но позвольте мне выполнить эту часть. Мне просто нужна часть регулярных выражений.

Мой взгляд с использованием PHP:

//This is php
$file = "test.au3"$lines = file($file)
foreach($lines as $index => $line){
$newLine = preg_replace(/*magic regex here*/);
}

Замена может быть сделана для каждой отдельной строки (у меня нет многострочных строк).

1

Решение

Это невозможно сделать с помощью одного регулярного выражения. Тем не менее, это может быть сделано с помощью регулярного выражения + анализ с учетом состояния.

Основываясь на возможных случаях синтаксиса в вашем примере, я собрал скрипт, который выполняет эту работу. Я написал его на Python, так как мне удобнее работать с этим языком, чем с PHP, но код + комментарии должны быть достаточно ясными, чтобы кто-то мог преобразовать их в PHP, если Python недоступен для этой задачи.

#!/usr/bin/env python
import fileinput
import re

# Values you might want to modify
filename = "test.au3"replacementFunctionName = "get_string"replacementForConcatenator = ","# Regexes to identify raw AutoIt elements
string = r"""(?:"(?:[^"]|"(?="))*"|'(?:[^']|'(?='))*')"""  # triple quotes is just Python
macro = r"@\w+"  # the prefix r makes the \ a literal (in the string, not the regex)
variable = r"\$\w+"concatenator = r"\s*&\s*"
# Regexes to identify compound AutoIt elements
nonConcatenator = "(?:" + string + "|" + macro + "|" + variable + ")"capturingNonConcatenator = "(" + string + "|" + macro + "|" + variable + ")"zeroOrMoreConcatenatedNonConcatenators = "(?:" + concatenator + nonConcatenator + ")" + "*"
# The combined search regex and its compiled form
search = string + zeroOrMoreConcatenatedNonConcatenators
searchRe = re.compile(search)  # compiling lets us specify a start index for searches# Process file in place
count = 0  # used to correctly number AutoIt string literal instances
for line in fileinput.input(filename, inplace=True):
newLine = ""
# Convert old line to new line
indexInLine = 0
matchOfSearchRe = searchRe.search(line, indexInLine)
while matchOfSearchRe is not None:
matchReplacement = ""
# Replace each AutoIt string in matched substring with number
# and replace each concatenator with a comma
elementsOfMatch = re.split(capturingNonConcatenator, matchOfSearchRe.group(0))
for elem in elementsOfMatch:
if re.match(string, elem):
count += 1
matchReplacement += str(count)
elif re.match(concatenator, elem):
matchReplacement += replacementForConcatenator
else:
matchReplacement += elem

# Place modified contents of match in a replacement function call
matchReplacement = replacementFunctionName + "(" + matchReplacement + ")"
# Append most recently skipped region before match and replacement for match
newLine += line[indexInLine:matchOfSearchRe.start()]
newLine += matchReplacement

# Update loop control variables
indexInLine = matchOfSearchRe.end()
matchOfSearchRe = searchRe.search(line, indexInLine)

# Append rest of line after final match
newLine += line[indexInLine:]

# Replace old line in filename with new line in place
print(newLine.rstrip())

На поверхностном тесте этот скрипт преобразован

;This is autoit
$string1 = "This is a test string" & @crlf & "Wow, autoit syntax!"$string2 = "This string has a var. Var1=" & $var1
$wow = random_function("Another string") & "this is getting complex"magic_function("var1=" & $var1 & @crlf & "other var=" & $var2)
$multivar = "This string has 2 vars: var1=" & $var1 & " var2=" & $var2

в

;This is autoit
$string1 = get_string(1,@crlf,2)
$string2 = get_string(3,$var1)
$wow = random_function(get_string(4)) & get_string(5)
magic_function(get_string(6,$var1,@crlf,7,$var2))
$multivar = get_string(8,$var1,9,$var2)

Если возможные варианты синтаксиса более разнообразны, чем в вашем примере, то этот сценарий не гарантированно будет работать. Однако его можно изменить в соответствии с вашими потребностями, просто добавив или изменив «регулярные выражения для идентификации необработанных элементов AutoIt» и связанные «регулярные выражения для идентификации составных элементов AutoIt». Любые изменения будут собраны в search переменная, так что больше ничего не нужно менять в основной части скрипта.

Обратите внимание, что я изменил ваш пример ввода в моем тестовом примере. Похоже, что ваш пример имел две синтаксические ошибки в последней строке: отсутствует & и дополнительный ",

0

Другие решения

Других решений пока нет …