如何查找字符串中正则表达式的所有匹配项

如何查找字符串中正则表达式的所有匹配项

分别在 POSIX awk 和 Gawk 中,我们如何找到字符串中正则表达式的所有匹配项?

gsub更具体地说,根据以下两个目标之一查找被内置函数替换的所有匹配项:

  • 找到目标字符串中每个匹配的位置和长度,以及

  • 仅查找作为目标字符串的子字符串的匹配项。

实现第一个目标意味着实现第二个目标。

  1. 在 POSIX awk 中,

    是否有一个内置函数可以实现这两个目标中的任何一个?

    内置函数是否match只找到最左边和最长的匹配?

    match为了实现第一个目标,重复应用通过查找每个匹配项并从目标字符串中删除匹配项及其前面的前缀而创建的目标字符串的后缀是否是正确的方法?是 https://gist.github.com/mllamazing/a40946fcf8211a503bed正确的实施?

  2. 在嘎嘎中,

    array 调用后是否patsplit(string, array, fieldpat, seps) 按照第二个目标的要求存储匹配项?根据 和之间的分隔符字符串,可以从array和中找到匹配位置的位置吗?sepsseps[i]array[i]array[i+1]

谢谢。

答案1

  1. 在 POSIX awk 中,
    是否有一个内置函数可以实现这两个目标中的任何一个?

不。您可以实现相同的效果,但不能使用单个内置函数。

内置函数是否match只找到最左边和最长的匹配?

是的。 POSIX awk(和 GNU awk)中的正则表达式总是贪婪的(即最长的匹配总是获胜)。

match为了实现第一个目标,重复应用通过查找每个匹配项并从目标字符串中删除匹配项及其前面的前缀而创建的目标字符串的后缀是否是正确的方法?

是的,但是如果你想要 100% 兼容gsub()细节就相当棘手了。

https://gist.github.com/mllamazing/a40946fcf8211a503bed正确的实施?

大多数情况下,如果您删除通用子线。问题在于细节:如果regex是空字符串,代码将循环。 Classicawk不允许空正则表达式,但 IIRCnawk允许。要解决这个问题,你可以这样做:

function FindAllMatches(str, regex, match_arr) {

    ftotal = 0;
    ini = RSTART;
    leng = RLENGTH;

    delete match_arr;

    while (str != "" && match(str, regex) > 0) {
        match_arr[++ftotal] = substr(str, RSTART, RLENGTH)
        str = substr(str, RSTART + (RLENGTH ? RLENGTH : 1))
    }

    RSTART = ini;
    RLENGTH = leng;
}

但这并不是 100% 兼容gsub(),因为

$ echo 123 | awk '{ gsub("", "-") } 1'
-1-2-3-

而上面的函数只找到 3 个匹配项(即,它错过了最后的匹配项)。

你可以试试这个:

function FindAllMatches(str, regex, match_arr) {

    ftotal = 0;
    ini = RSTART;
    leng = RLENGTH;

    delete match_arr;

    while (match(str, regex) > 0) {
        match_arr[++ftotal] = substr(str, RSTART, RLENGTH)
        if (str == "") break
        str = substr(str, RSTART + (RLENGTH ? RLENGTH : 1))
    }

    RSTART = ini;
    RLENGTH = leng;
}

这解决了上面的问题,但它打破了其他情况: ifstr = "123"regex = "[1-9]*"函数找到两次出现,123并且末尾有空字符串,而 whilegsub()只找到一个,123

可能还有其他类似的差异,我现在懒得去寻找。

  1. 在嘎嘎中,

    array 调用后是否patsplit(string, array, fieldpat, seps) 按照第二个目标的要求存储匹配项?

大多数情况下是的。然而,与正则表达式相关的极端情况可能出乎意料地微妙。可能有一些差异,如上所述。

根据 和之间的分隔符字符串,可以从array和中找到匹配位置的位置吗?sepsseps[i]array[i]array[i+1]

是的。

相关内容