regex重复捕获组捕获最后一次迭代,但我需要全部



示例代码:

var reStr = `"(?:\"|[^"])*"`
var reStrSum = regexp.MustCompile(`(?m)(` + reStr + `)s*+s*(` + reStr + `)s*+s*(` + reStr + `)`)
var str = `"Thisnista\string" + 
"Another"string" + 
"Third string"
`
for i, match := range reStrSum.FindAllStringSubmatch(str, -1) {
fmt.Println(match, "found at index", i)
for i, str := range match {
fmt.Println(i, str)
}
}

输出:

["Thisnista\string" + 
"Another"string" + 
"Third string" "Thisnista\string" "Another"string" "Third string"] found at index 0
0 "Thisnista\string" + 
"Another"string" + 
"Third string"
1 "Thisnista\string"
2 "Another"string"
3 "Third string"

例如,它与";字符串之和";并且它正确地捕获了所有三个字符串。

我的问题是,我不想正好匹配三个字符串的和。我想匹配所有";字符串之和";其中总和可以由一个或多个字符串文字组成。我试着用{0,}来表达这一点

var reStr = `"(?:\"|[^"])*"`
var reStrSum = regexp.MustCompile(`(?m)(` + reStr + `)` + `(?:s*+s*(` + reStr + `)){0,}`)
var str = `
test1("Thisnista\string" + 
"Another"string" + 
"Third string summed");
test2("Second string " + "sum");
`
for i, match := range reStrSum.FindAllStringSubmatch(str, -1) {
fmt.Println(match, "found at index", i)
for i, str := range match {
fmt.Println(i, str)
}
}
`)){0,}`)

然后我得到这个结果:

["Thisnista\string" + 
"Another"string" + 
"Third string summed" "Thisnista\string" "Third string summed"] found at index 0
0 "Thisnista\string" + 
"Another"string" + 
"Third string summed"
1 "Thisnista\string"
2 "Third string summed"
["Second string " + "sum" "Second string " "sum"] found at index 1
0 "Second string " + "sum"
1 "Second string "
2 "sum"

第一个匹配的组0包含所有三个字符串(regexp匹配正确(,但表达式中只有两个捕获组,第二个组只包含重复的最后一次迭代。例如"Another"string"在过程中丢失,无法访问。

有可能以某种方式在第2组内获得所有迭代(所有重复(吗?

我也接受任何使用嵌套循环的变通方法。但请注意,我不能简单地用外部FindAllStringSubmatch调用替换{0,}重复,因为FindAllStringSubmatch调用已经用于迭代"0";字符串的和";。换句话说,我必须找到第一个字符串和以及"Second string sum"

我刚刚找到了一个可行的解决方法。我能传球两次。在第一步中,我只匹配所有字符串文字,并在原始文本中用唯一的占位符替换它们。然后转换后的文本将不包含任何字符串,并且在第二次传递中对其进行进一步处理变得容易得多

类似这样的东西:

type javaString struct {
value  string
lineno int
}

// First we find all string literals
var placeholder = "JSTR"
var reJavaStringLiteral = regexp.MustCompile(`(?m)("(?:\"|[^"])*")`)
javaStringLiterals := make([]javaString, 0)
for pos, strMatch := range reJavaStringLiteral.FindAllStringSubmatch(strContent, -1) {
pos = strings.Index(strContent, strMatch[0])
head := strContent[0:pos]
lineno := strings.Count(head, "n") + 1
javaStringLiterals = append(javaStringLiterals, javaString{value: strMatch[1], lineno: lineno})
}
// Next, we replace all string literals with placeholders.
for i, jstr := range javaStringLiterals {
strContent = strings.Replace(strContent, jstr.value, fmt.Sprintf("%v(%v)", placeholder, i), 1)
}
// Now the transformed text does not contain any string literals.

第一次通过后,原始文本变为:

test1(JSTR(1) +
JSTR(2) +
JSTR(3));
test2(JSTR(3) + JSTR(4));

经过这一步,我可以很容易地找到"JSTR(\d+(+JSTR([d+(+JSTR(\d+"表达式。现在它们很容易找到,因为文本不包含任何字符串(否则可能包含任何内容并干扰正则表达式(。这些";字符串之和";然后可以将匹配项与另一个FindAllStringSubmatch重新匹配(在内部循环中(,然后我将获得所需的所有信息。

这不是一个真正的解决方案,因为它需要编写大量代码,它特定于我的具体用例,并不能真正回答最初的问题:允许访问重复捕获组中的所有迭代。

但解决方法的总体思路可能对面临类似问题的人有利。

相关内容

最新更新