regex awk中多字符分隔符的非贪婪正则表达式匹配

vwkv1x7d  于 2023-08-08  发布在  其他
关注(0)|答案(4)|浏览(148)

考虑字符串"AB 1 BA 2 AB 3 BA"。如何以非贪婪的方式(在awk中)匹配"AB""BA"之间的内容?
我尝试了以下几点:

awk '
BEGIN {
    str="AB 1 BA 2 AB 3 BA"
    regex="AB([^B][^A]|B[^A]|[^B]A)*BA"
    if (match(str,regex))
        print substr(str,RSTART,RLENGTH)
}'

字符串
没有输出。我认为不匹配的原因是"AB""BA"之间有奇数个字符。如果我用"AB 11 BA 22 AB 33 BA"替换str,正则表达式似乎可以工作。

bprjcwpo

bprjcwpo1#

合并两个取反的字符类,并从第二个替换中删除[^A]

regex = "AB([^AB]|B|[^B]A)*BA"

字符串
这个正则表达式在字符串ABABA上失败,但是-不确定这是否是一个问题。

说明:

AB       # Match AB
(        # Group 1 (could also be non-capturing)
 [^AB]   # Match any character except A or B
|        # or
 B       # Match B
|        # or
 [^B]A   # Match any character except B, then A
)*       # Repeat as needed
BA       # Match BA


由于在交替中匹配A的唯一方法是匹配B之前的字符,因此我们可以安全地使用简单的B作为替代方案之一。

5cg8jx4n

5cg8jx4n2#

另一个答案并没有真正回答:如何进行非贪婪匹配?看起来它不能在(G)AWK中完成。手册上是这么说的:
awk(和POSIX)正则表达式总是匹配最左边、最长的输入字符序列。
https://www.gnu.org/software/gawk/manual/gawk.html#Leftmost-Longest
整本手册都没有“贪婪”或“懒惰”的字眼。它提到了扩展正则表达式,但for greedy matching you'd need Perl-Compatible Regular Expressions。所以不行

hgncfbus

hgncfbus3#

对于一般表达式,我使用以下内容作为非贪婪匹配:

function smatch(s, r) {
    if (match(s, r)) {
        m = RSTART
        do {
            n = RLENGTH
        } while (match(substr(s, m, n - 1), r))
        RSTART = m
        RLENGTH = n
        return RSTART
    } else return 0
}

字符串
smatch的行为类似于match,返回:
s中正则表达式r出现的位置,如果没有,则为0。变量RSTARTRLENGTH被设置为匹配字符串的位置和长度。

qij5mzcb

qij5mzcb4#

使用特殊文本(退格键或\x00或类似文本)标记字段,然后在gsub命令中包含字段拆分器以删除额外的字段拆分器。

$1="\b";
gsub("\b"FS,"")

字符串

相关问题