如何用正则提取脚本输出中各文件名对应的首个内存地址?
问题描述
我有一段脚本返回的如下文本:
7d60f000-7d67b000 r-xp 00000000 fb:00 11 /bin/busybox.nosuid 7d68b000-7d68c000 r--p 0006c000 fb:00 11 /bin/busybox.nosuid 7d68c000-7d68d000 rw-p 0006d000 fb:00 11 /bin/busybox.nosuid b3dfb000-b3ebe000 r-xp 00000000 fb:00 1636 /lib/libc-2.31.so b3ebe000-b3ecd000 ---p 000c3000 fb:00 1636 /lib/libc-2.31.so b3ecd000-b3ecf000 r--p 000c2000 fb:00 1636 /lib/libc-2.31.so b3ecf000-b3ed1000 rw-p 000c4000 fb:00 1636 /lib/libc-2.31.so b3ed1000-b3ed3000 rw-p 00000000 00:00 0 b3ed3000-b3f24000 r-xp 00000000 fb:00 1655 /lib/libm-2.31.so b3f24000-b3f33000 ---p 00051000 fb:00 1655 /lib/libm-2.31.so b3f33000-b3f34000 r--p 00050000 fb:00 1655 /lib/libm-2.31.so b3f34000-b3f35000 rw-p 00051000 fb:00 1655 /lib/libm-2.31.so b3f35000-b3f36000 r-xp 00000000 fb:00 4296 /usr/lib/libcrashlog.so.0.0.0 b3f36000-b3f45000 ---p 00001000 fb:00 4296 /usr/lib/libcrashlog.so.0.0.0 b3f45000-b3f46000 r--p 00000000 fb:00 4296 /usr/lib/libcrashlog.so.0.0.0 b3f46000-b3f47000 rw-p 00001000 fb:00 4296 /usr/lib/libcrashlog.so.0.0.0 b3f47000-b3f5d000 r-xp 00000000 fb:00 1628 /lib/ld-2.31.so b3f6b000-b3f6d000 rw-p 00000000 00:00 0 b3f6d000-b3f6e000 r--p 00016000 fb:00 1628 /lib/ld-2.31.so b3f6e000-b3f6f000 rw-p 00017000 fb:00 1628 /lib/ld-2.31.so
我想要为每个文件名提取对应的首个内存地址,例如:
- 对于
/bin/busybox.nosuid,返回7d60f000-7d67b000 - 对于
/lib/libc-2.31.so,返回b3dfb000-b3ebe000 - 对于
/lib/libm-2.31.so,返回b3ed3000-b3f24000 - 对于
/usr/lib/libcrashlog.so.0.0.0,返回b3f35000-b3f36000 - 对于
/lib/ld-2.31.so,返回b3f47000-b3f5d000
请问是否可以通过正则表达式实现这一需求?
解决方案
完全可以通过正则表达式配合简单的去重逻辑实现需求,以下是具体实现方案:
核心思路
- 正则匹配规则:每行开头的内存地址是
[0-9a-f]+-[0-9a-f]+格式的字符串,文件名在每行末尾。可以用正则捕获这两个关键部分:^([0-9a-f]+-[0-9a-f]+).*?(\/[\w\/\.-]+)$^([0-9a-f]+-[0-9a-f]+):捕获行首的内存地址段.*?:非贪婪匹配中间的任意字符(\/[\w\/\.-]+)$:捕获行末的完整文件名
- 去重处理:同一个文件会出现多次,只需记录首次捕获到的内存地址即可。
具体实现示例
用awk实现(轻量高效)
直接用awk的数组去重,一行代码就能搞定:
awk '!seen[$NF]++ {print "对于`" $NF "`,返回`" $1 "`"}' input.txt
解释:
$NF表示每行最后一个字段(即文件名)!seen[$NF]++:仅当文件名第一次出现时执行后续打印操作print语句按照需求格式输出结果
用Python实现(灵活可控)
如果需要更复杂的后续处理,用Python结合正则实现:
import re record = {} # 定义匹配正则 pattern = re.compile(r'^([0-9a-f]+-[0-9a-f]+).*?(\/[\w\/\.-]+)$') # 读取并处理每行内容 with open('input.txt', 'r') as f: for line in f: line = line.strip() if not line: continue match_result = pattern.match(line) if match_result: addr = match_result.group(1) fname = match_result.group(2) # 仅记录首次出现的地址 if fname not in record: record[fname] = addr # 按需求格式输出 for fname, addr in record.items(): print(f"对于`{fname}`,返回`{addr}`")
输出结果
运行上述任意一种方法,都会得到你需要的结果:
- 对于
/bin/busybox.nosuid,返回7d60f000-7d67b000 - 对于
/lib/libc-2.31.so,返回b3dfb000-b3ebe000 - 对于
/lib/libm-2.31.so,返回b3ed3000-b3f24000 - 对于
/usr/lib/libcrashlog.so.0.0.0,返回b3f35000-b3f36000 - 对于
/lib/ld-2.31.so,返回b3f47000-b3f5d000
内容的提问来源于stack exchange,提问作者Psl
相关产品推荐
相关产品推荐

