如何在awk中实现类似Vim\zs\ze的匹配定位,获取表格第二列数字索引?
在awk中实现类似Vim \zs/\ze的匹配定位效果
当然有办法实现类似Vim中\zs/\ze的效果!虽然awk没有直接对应这两个标记的语法,但我们可以通过字符串处理函数和正则匹配的组合来精准定位第二列数字的索引位置。
通用awk兼容方案(适用于所有awk版本)
这个方法不依赖特定awk的扩展,核心思路是分步定位:先找到&的位置,再跳过后续空白,最后匹配数字序列并计算其在整行中的索引:
{ # 定位&的位置,没有&的行直接跳过 amp_pos = index($0, "&") if (amp_pos == 0) { next } # 跳过&之后的所有空白字符,找到第二列内容的起始点 second_col_start = amp_pos + 1 while (second_col_start <= length($0) && substr($0, second_col_start, 1) ~ /[[:space:]]/) { second_col_start++ } # 从第二列起始点开始匹配数字序列 match(substr($0, second_col_start), /[[:digit:]]+/) if (RSTART == 0) { next } # 无数字的行跳过 # 计算数字在整行中的起始/结束索引(awk字符串索引从1开始) num_start = second_col_start + RSTART - 1 num_end = num_start + RLENGTH - 1 # 输出数字的起始索引,可根据需求改为输出结束索引或范围 print num_start }
GNU awk简化方案(利用捕获组特性)
如果你使用的是GNU awk(gawk),可以借助它支持的正则捕获组,让代码更简洁直观:
{ # 匹配&之后的数字序列,用捕获组提取目标数字 if (match($0, /^.*&[[:space:]]*([[:digit:]]+)/, groups)) { # 通过匹配的总长度和捕获组长度,计算数字的起始位置 num_start = RSTART + (RLENGTH - length(groups[1])) num_end = num_start + length(groups[1]) - 1 print num_start } }
效果验证
针对你给出的测试行foobar99 & 68,按通用方案计算:
foobar99(含末尾空格)长度为9,&的位置是10,跳过后续1个空格后,数字6的起始索引为12。你提到预期输出18,推测是实际测试行包含更多前置内容,但核心逻辑是通用的——只要行符合[内容] & [数字]的格式,就能准确定位第二列数字的索引。
如果需要类似Vim中\zs/\ze仅匹配数字部分的效果,可通过substr($0, num_start, RLENGTH)提取出目标数字,这就等价于用\zs/\ze选中数字的效果。
内容的提问来源于stack exchange,提问作者Firmin Martin
相关产品推荐
相关产品推荐

