正则表达式替换:函数调用的字符串

时间:2017-01-25 23:42:00

标签: php regex string replace autoit

我的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)

OR

;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 个答案:

答案 0 :(得分:0)

单靠正则表达式无法做到这一点。但是,可以使用正则表达式+有状态解析来完成。

根据您示例中可能的语法案例,我已经整理了一个完成工作的脚本。我用Python编写它,因为我比PHP更熟悉这种语言,但代码+注释应该足够清楚,如果没有Python可用于此任务,有人将其转换为PHP。

#!/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变量中收集任何修改,以便在脚本的主体中不需要更改任何其他内容。

请注意,我在测试用例中修改了您的示例输入。您的示例似乎在最后一行有两个语法错误:缺少&和额外的"