如何用sed/awk/Python将日志语句捕获组替换为文件名:行号?
需求:批量给日志语句插入文件名和行号
我需要给源代码里的日志语句批量插入文件名:行号信息,替换日志方法调用的第一个字符串参数:
- 原语句示例:
logger.e("", "an error happened");
- 替换后效果:
logger.e("filename:123", "an error happened, this is the line number the last time I edited the file.")
注意:如果已执行过替换,无需重复处理。
背景与已有尝试
我计划在构建流水线中实现该文本处理工具,最初尝试用awk但未成功,现接受任何合适工具。
我编写了正则表达式用于匹配目标内容并捕获第一个字符串参数:
logger\.[tdiwe]\("(.*?)"
该正则匹配以logger.t/d/i/w/e(开头的日志调用,意图通过"(.*?)"将第一对双引号内的内容放入捕获组,但不确定写法是否准确。测试多款工具后发现,提取捕获组难度不高,但替换时遇到问题。
我已用Python实现需求,但流程繁琐,希望找到更简便的方案:
with open(infilename) as infile: with open(outfilename, "w") as outfile: linenumber = 1 for line in infile: rslt = re.search(r'logger\.[tdiwe]\("([^"]*)', line) if rslt: outfile.write(line[:rslt.span(1)[0]] + f"filename:{str(linenumber)}" + line[rslt.span(1)[1]:]) else: outfile.write(line) linenumber += 1
更简便的替代方案
方案1:GNU sed 单文件/批量处理
GNU sed支持正则捕获与行号变量,可直接原地修改文件:
# 单文件处理,生成.bak备份文件 sed -i.bak -E "s/(logger\.[tdiwe]\(\").*?(\",)/\1$(basename "your_source_file.java"):\&\2/g" your_source_file.java # 批量处理.java文件 for file in *.java; do sed -i.bak -E "s/(logger\.[tdiwe]\(\").*?(\",)/\1$(basename "$file"):\&\2/g" "$file" done
-i.bak:原地修改并保留原文件备份,去掉.bak可省略备份-E:启用扩展正则表达式\1/\2:分别捕获logger.t/d/i/w/e("和",片段$(basename "$file"):获取当前处理文件的文件名\&:代表当前行号
方案2:awk 精准处理
awk可直接获取文件名与行号,处理逻辑更直观:
awk -v OFS="" '{ match($0, /logger\.[tdiwe]\("([^"]*)"/, arr) if (arr[0] != "") { start = RSTART + length("logger.[tdiwe](\"") end = start + length(arr[1]) $0 = substr($0, 1, start-1) FILENAME ":" NR substr($0, end+1) } print }' your_source_file.java > output_file.java
match(..., arr):用正则匹配目标内容,arr[1]为第一对双引号内的原内容RSTART:匹配内容的起始位置,结合长度计算替换区间FILENAME/NR:分别代表当前处理文件名与行号- 输出到新文件,若需原地修改可结合临时文件中转
注意事项
- 用
[^"]*替代.*?更可靠,可避免匹配到后续引号 - 若存在跨行的日志调用,上述工具处理受限,此时Python逐行方案仍为最优选择
- 执行前建议备份文件,避免误修改
内容的提问来源于stack exchange,提问作者Nevo
相关产品推荐
相关产品推荐

