如何获取文件中匹配模式的文件名、行号及行内字节偏移?
解决方案:获取匹配模式的文件名、行号及行内字节偏移
一、Shell脚本实现
可以结合grep和awk计算行内偏移,通过全局偏移减去当前行之前的总字节数,得到相对于行开头的偏移量。
示例命令
假设搜索模式为a,目标文件为file.txt:
grep --with-filename -n -r -E -o -b "a" file.txt | awk -F: '{ cmd = "head -n " ($2-1) " " $1 " | wc -c" cmd | getline line_start close(cmd) print $1 ":" $2 ":" ($3 - line_start) ":" $4 }'
说明
grep --with-filename -n -r -E -o -b "a" file.txt:输出格式为file.txt:1:0:a,第三个字段是基于整个文件的全局字节偏移。awk处理逻辑:- 执行
head -n (行号-1) 文件名 | wc -c,计算当前行之前所有内容的总字节数(包含换行符)。 - 用全局偏移减去该数值,得到行内的字节偏移。
- 按
文件名:行号:行内偏移:行内容格式输出结果。
- 执行
二、Python脚本实现
Python方案更灵活,可避免shell命令的兼容性问题,以下是实现代码:
代码示例
import re import os def search_pattern(pattern, target_path): # 递归遍历目标路径下的所有文件 for root, _, files in os.walk(target_path): for filename in files: file_full_path = os.path.join(root, filename) # 二进制模式读取,确保字节偏移计算准确 with open(file_full_path, 'rb') as f: line_number = 0 while True: line_bytes = f.readline() if not line_bytes: break line_number += 1 # 查找当前行内所有匹配的位置 for match in re.finditer(pattern.encode(), line_bytes): line_offset = match.start() # 转换为字符串显示行内容(默认utf-8编码,可根据实际调整) line_content = line_bytes.decode('utf-8').rstrip('\n') print(f"{file_full_path}:{line_number}:{line_offset}:{line_content}") # 使用示例:搜索模式"a",当前目录下的所有文件 search_pattern(r"a", ".")
说明
- 用
os.walk递归遍历目标路径下的所有文件。 - 二进制模式读取文件,避免编码转换导致的偏移误差。
re.finditer获取每行内所有匹配的起始位置,该位置即为行内字节偏移。- 按指定格式输出结果,兼容多文件递归搜索场景。
测试结果
对于示例文件file.txt:
abc def xyzva
搜索模式a会输出:
file.txt:1:0:abc file.txt:3:4:xyzva
内容的提问来源于stack exchange,提问作者Lazy Enthusiast
相关产品推荐
相关产品推荐

