Tim*_*Tim 5 awk text-processing regular-expression gawk
分别在 POSIX awk 和 Gawk 中,我们如何在字符串中找到与正则表达式的所有匹配项?
更具体地说,gsub
根据以下两个目标之一,找到被内置函数替换的所有匹配项:
找到目标字符串中每个匹配项的位置和长度,以及
仅将匹配项作为目标字符串的子字符串查找。
实现第一个目标意味着实现第二个目标。
在 POSIX awk 中,
是否有内置函数可以实现这两个目标中的任何一个?
match
内置函数是否只找到最左边和最长的匹配项?
为了实现第一个目标,match
通过查找每个匹配项并从目标字符串中删除匹配项及其前面的前缀来重复应用到目标字符串的后缀是否是正确的方法?被
https://gist.github.com/mllamazing/a40946fcf8211a503bed正确实施?
在 Gawk 中,
没有array
一个电话后,patsplit(string, array, fieldpat, seps)
存储的匹配,而在第二个目标需要?是否可以从array
and 中找到匹配位置的位置seps
,基于它seps[i]
是array[i]
和之间的分隔符字符串array[i+1]
?
谢谢。
- 在 POSIX awk 中,
是否有一个内置函数可以实现这两个目标中的任何一个?
不。您可以实现相同的效果,但不能使用单个内置函数。
内置函数是否
match
只找到最左边和最长的匹配?
是的。POSIX awk
(和 GNU awk
)中的正则表达式总是贪婪的(即最长的匹配总是获胜)。
为了实现第一个目标,重复应用
match
通过查找每个匹配项并从目标字符串中删除匹配项及其前面的前缀而创建的目标字符串的后缀是否是正确的方法?
是的,但是如果你想要 100% 兼容gsub()
细节就相当棘手了。
https://gist.github.com/mllamazing/a40946fcf8211a503bed是正确的实现吗?
大多数情况下,如果删除gsub 行。问题在于细节:如果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;
}
Run Code Online (Sandbox Code Playgroud)
但这并不是 100% 兼容gsub()
,因为
$ echo 123 | awk '{ gsub("", "-") } 1'
-1-2-3-
Run Code Online (Sandbox Code Playgroud)
而上面的函数只找到 3 个匹配项(即,它错过了最后的匹配项)。
你可以试试这个:
$ echo 123 | awk '{ gsub("", "-") } 1'
-1-2-3-
Run Code Online (Sandbox Code Playgroud)
这解决了上面的问题,但它打破了其他情况: ifstr = "123"
和regex = "[1-9]*"
函数找到两次出现,123
并且末尾有空字符串,而 whilegsub()
只找到一个,123
。
可能还有其他类似的差异,我现在懒得去寻找。
在嘎嘎中,
array
调用后是否patsplit(string, array, fieldpat, seps)
按照第二个目标的要求存储匹配项?
大多数情况下是的。然而,与正则表达式相关的极端情况可能出乎意料地微妙。如上所述,可能存在一些差异。
根据 和之间的分隔符字符串,可以从
array
和中找到匹配位置的位置吗?seps
seps[i]
array[i]
array[i+1]
是的。
归档时间: |
|
查看次数: |
1989 次 |
最近记录: |