【问题标题】:Regex replacement: strings to function call正则表达式替换:函数调用的字符串
【发布时间】:2017-06-11 08:22:45
【问题描述】:

我的 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*/);
}

可以对每一行进行替换(我没有多行字符串)。

【问题讨论】:

    标签: php regex string replace autoit


    【解决方案1】:

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

    根据您的示例中可能出现的语法情况,我整理了一个完成这项工作的脚本。我用 Python 编写了它,因为我比 PHP 更熟悉这种语言,但是如果 Python 无法用于此任务,代码 + cmets 应该足够清晰,以便有人将其转换为 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 变量中,因此脚本主体中不需要更改任何其他内容。

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

    【讨论】:

      猜你喜欢
      • 2018-07-13
      • 2015-11-30
      • 2021-11-29
      • 2017-02-04
      相关资源
      最近更新 更多