如何编写Awk的ere_parenthesize函数,为任意ERE加括号并保留原意
实现Awk的ERE括号包裹函数ere_parenthesize
要实现一个能正确将扩展正则表达式(ERE)用括号包裹的Awk函数,确保在match、split、sub等函数中保留原语义,需解决原简单实现未处理的括号嵌套、转义字符、字符类等问题。
原错误实现
最初的简单实现未考虑ERE中存在未匹配或嵌套的右括号,会导致语法错误:
function ere_parenthesize(ere) { return "(" ere ")" }
正确实现思路
需要遍历ERE字符串,跟踪以下状态:
- 括号嵌套层级:避免未匹配的
)提前闭合外层添加的括号 - 是否处于字符类中:字符类中的括号是字面量,不参与层级计算
- 转义字符:转义后的括号是字面量,不影响层级
- POSIX引擎兼容性:通过
is_posix_ere_engine = match("\\", /[\^]/)判断引擎类型,调整转义处理逻辑
完整函数实现
function ere_parenthesize(ere, is_posix, res, i, len, depth, in_class, c) { is_posix = match("\\", /[\^]/) res = "" len = length(ere) depth = 0 in_class = 0 for (i = 1; i <= len; i++) { c = substr(ere, i, 1) if (in_class) { res = res c if (!is_posix && c == "\\") { i++ res = res substr(ere, i, 1) } else if (c == "]") { in_class = 0 } continue } if (c == "\\") { res = res c i++ res = res substr(ere, i, 1) continue } if (c == "[") { res = res c in_class = 1 continue } if (c == "(") { depth++ res = res c continue } if (c == ")") { if (depth > 0) { depth-- res = res c } else { res = res "\\)" } continue } res = res c } if (in_class) { res = res "\\]" } while (depth > 0) { res = res "\\)" depth-- } return "(" res ")" }
示例输入输出
| 输入ERE | 预期输出 | 说明 |
|---|---|---|
a|b | (a|b) | 普通表达式直接包裹 |
a(b)c | (a(b)c) | 嵌套括号正确保留层级 |
a)b | (a\)b) | 未匹配的)被转义为字面量 |
[()] | ([()]) | 字符类中的括号视为字面量 |
a\|(b)c | (a\|(b)c) | 转义字符保留原语义 |
函数特性
- 自动处理括号嵌套,确保外层括号不会被提前闭合
- 正确识别字符类中的字面量括号
- 兼容POSIX与非POSIX正则引擎
- 自动修复未闭合的
[或(,转义对应的字符以保证表达式合法
内容的提问来源于stack exchange,提问作者Fravadona
相关产品推荐
相关产品推荐

