Notepad++正则替换实战:批量给16进制数字加0x前缀

发布时间:2026/10/20 17:14:29
Notepad++正则替换实战:批量给16进制数字加0x前缀
老话讲“磨刀不误砍柴工”但很多搞嵌入式和底层开发的兄弟恰恰就栽在这把“刀”上。我举个例子你手头有一份寄存器地址表、一张CAN报文ID清单或者是一串从逻辑分析仪里导出的内存dump数据整整几十行、几百个十六进制数现在要贴进C代码里做宏定义或者初始化数组。你当然可以一个一个手动加0x但那种机械式复制粘贴的酸爽试过一次就再也不想试第二次。更让人头疼的是这类操作还不能光靠宏录制搞定因为每个数字的长度不一样位置也不固定。我早些年是被这种重复劳动折磨到不行才认认真真把Notepad的正则替换研究透了。现在遇到这类需求基本上十秒内解决而且替换完还能顺手把格式、对齐、大小写一并处理好。这篇东西没什么高深理论就是纯实战经验专门讲清楚“Notepad里如何给16进制数字批量加上0x前缀”顺便把它背后的匹配原理和坑点都给你拆明白保证你看完能直接照着操作。1. 需求拆解与前置思考先别急着按CtrlH我们花两分钟想清楚一个问题你面对的数据到底长什么样以及你到底想得到什么结果。很多人一上来就搜“加前缀”但最后往往发现光加前缀不够后面还要去掉空格、补位、转大写甚至要把0X和0x统一成一种风格。1.1 你真正要解决的其实不止“加前缀”这一件事举个最常见的场景。假设某项目的寄存器配置表长这样00 01 0A 1F FF 2C 3D 4E 50 71你要把它转成一个C语言数组uint8_t config[] { 0x00, 0x01, 0x0A, 0x1F, 0xFF, 0x2C, 0x3D, 0x4E, 0x50, 0x71 };这个转换过程至少包含四件事加0x、把空格换成逗号、每10个数字换行、行尾补逗号并处理缩进。只看“加前缀”确实是最核心的一步但如果你的思路只停留在这一步后面还得折腾好几轮。另一种更常见的情况是数据已经混在文本堆里地址0x100处的值是A0地址0x108处的值是F3这时候你要做的反而是把A0、F3这些裸数字识别出来并补上0x但0x100里的100绝对不能动。这类“挑着改”的需求用宏录制完全做不到因为判断逻辑比物理操作复杂得多必须靠正则表达式的匹配规则来圈定范围。所以我倾向于先把需求拆成三个层次第一层是纯加前缀第二层是只对特定形态的数字加前缀第三层是加完前缀后顺带完成格式整理。想清楚你在哪一层再去操作才不会做无用功。1.2 为什么选 Notepad 而不是 Excel、脚本或在线工具遇到这类批量文本处理有人会问为什么不用Excel为什么不用Python脚本为什么不上在线工具我的回答是工具没有绝对好坏关键是看数据在哪儿、操作成本和出错概率。Excel擅长的是结构化二维表对“全文查找并条件替换”这种纯文本操作反而很别扭。你要先把文本按分隔符拆开、挨个处理完再拼回去这个过程中格式很容易错乱而且对于杂排在散文式文本里的数字完全无能为力。Python脚本倒是全能但为了一次性、只有五十行的地址表专门写脚本属于杀鸡用牛刀。你得考虑环境里有没有解释器、正则转义有没有写错、脚本跑完怎么验证这前前后后的时间早够你在编辑器里手动改两遍了。至于在线工具最大的隐患是数据安全。寄存器表、协议定义、未公开的固件信息这些往往都是敏感资料往第三方网站上一贴等于裸奔。所以我的结论很明确本地编辑器内置的批量替换和正则引擎是这类需求的最优解。而Notepad作为轻量级编辑器它的正则替换能力完全够用启动快、内存占用小、操作又直观处理几MB以内的文本毫无压力。2. 核心实操用正则替换批量加0x好了正式进入操作环节。前面做了那么多铺垫其实就是为了让这一节的操作能一步到位。我还是按“从简到繁”的顺序来拆解先讲最基础、最常用的方案再讲它的局限性和进阶加强版。2.1 最简版本匹配一段连续16进制字符打开Notepad按CtrlH呼出替换对话框在“查找模式”里勾选“正则表达式”。然后查找目标\b[0-9A-Fa-f]\b替换为0x$0点击“全部替换”这个正则看起来简单但里面每一个符号都不是白给的。[0-9A-Fa-f]是定义一个字符集合代表任意一个十六进制数字字符大小写都接受后面的表示前面的字符出现一次或多次所以它能匹配F、3F、A1B2这种长度不等的串。关键在两端各有一个\b这玩意儿叫“单词边界”它的作用是声明匹配位置必须在字母数字和空白、标点或字符串开头结尾的交界处。为什么要加边界因为不加的话正则引擎会把0x100里的x100截出来也会把A1B2C3里的B2C3单独截出来结果就是一团乱麻。\b保证了我们匹配的是“独立成词”的十六进制数前一个字符不是数字或字母后一个字符也不是数字或字母这样才不会误伤别人。替换成0x$0是什么意思呢$0代表匹配到的整个内容。也就是说不管匹配到的是2还是A1B2直接原样保留并在它前面拼上0x。运行之后00 01 0A 1F FF就变成了0x00 0x01 0x0A 0x1F 0xFF目标达成。2.2 边界陷阱正则里容易被忽略的“单词边界”\b这个符号用好了是神器用错了是灾难。很多人直接把上面的方案用到实际数据里结果发现改出来的东西根本没法看。问题不出在正则本身而是出在“单词边界”的定义上。这里必须提醒一个关键细节\b并不是“句号逗号”意义上的中文词边界它的判断依据是\w这个字符集合也就是[A-Za-z0-9_]。换句话说下划线是被它当作单词字符的一部分来对待的。这就产生了一个很常见的坑。比如你有一段数据REG1_ADDR A0 REG2_ADDR B3你想给A0、B3加0x但REG1_ADDR里的下划线把前后隔开了A0和ADDR之间没有边界\b[0-9A-Fa-f]\b根本不会在A0这里命中。你得把正则改成(?![0-9A-Fa-f_])[0-9A-Fa-f](?![0-9A-Fa-f_])用负向断言来排除下划线影响这样才能把紧贴下划线的数字也挑出来。另外如果数据里存在像A0.FF这样带小数点的串\b会把A0和FF当成两个独立的单词各加一个0x结果变成0xA0.0xFF这显然不是你要的。所以看到这里你就明白了没有万能的正则只有先认清数据形态、再选对应规则的思路。我习惯的做法是在真正“全部替换”之前先点一次“查找下一个”一个个看匹配结果确认没有误伤再动手。这个习惯能帮你省掉大把回滚的时间。2.3 从测试到应用的完整流程既然说到了验证我就把一套完整的操作顺序列出来照着走基本不会翻车。第一步备份原始数据。我不管你是复制到旁边的临时文件里还是直接在编辑器里按CtrlZ撤销到底总而言之得留一条后路。正则替换是不可逆操作万一你写了个灾难级规则一秒钟就把整个文件的格式毁了没有备份就只能哭。第二步用“查找下一个”单步验证。在替换对话框里千万别急着点“全部替换”先点几次“查找下一个”观察高亮区域是不是你想要的形态。这一步的重点是看边界比如数字前后紧挨着的字符是什么有没有把123这种十进制数也挑出来有没有漏掉A到F的大写字母。第三步小范围替换。如果你有把握可以在“替换”按钮上单次点一下让第一个匹配被替换观察格式对不对如果对继续。如果文本量不大我更推荐先选中一部分数据再勾选“选区内替换”这样就算规则出了意外也只影响那一片内容。第四步全部替换后快速抽查。替换完成后用CtrlF搜索0x0x看看有没有双重前缀的痕迹再搜一下[^0-9A-Fa-f]0[^x0-9A-Fa-f]之类的模式确认没有漏掉的大写字母串。这里的核心是正则替换不是终点验证才是。3. 进阶玩法与周边扩展基础版搞定了多数场景其实已经能应付。但实际项目中总会冒出一些“稍微复杂一点”的需求比如只要给两位数的改、要把生成的代码风格统一成大写、或者数据里混着别的进制。这一节我把常见进阶玩法摊开讲。3.1 限制长度与位宽只匹配2位、4位或8位的数字很多时候你要处理的寄存器或者地址总线的位宽是固定的。比如某项目的配置值只用8位那所有有效值都在00到FF之间有的协议字段是16位那有效值就是四位十六进制。这时候就需要限制匹配长度而不是笼统地匹配“一段16进制字符”。正则里的量词可以精确控制次数写法如下只匹配2位十六进制\b[0-9A-Fa-f]{2}\b替换为0x$0只匹配4位十六进制\b[0-9A-Fa-f]{4}\b匹配2到4位\b[0-9A-Fa-f]{2,4}\b匹配1到8位\b[0-9A-Fa-f]{1,8}\b这个写法对于寄存器位宽明确、又不想误伤长数据的场景极其有用。举个例子一份文件里既有FF这种两位的协处理器指令又有20A1这种四位的内存地址如果你笼统地用[0-9A-Fa-f]去匹会把20A1整体当一个数处理导致后面的场景全乱套。用{2}限定位宽以后20A1根本不在匹配范围内直接跳过非常干净。这里还需要解释一下{2,4}这种写法匹配的是“至少2位、最多4位”的连续数字。有人会问那它会不会把F给漏掉会因为F只有1位不在区间内这样设计是合理的。也有人会问那一个6位的数字会不会被从中间截一段出来匹配成4位答案是会比如123456会被截出1234来命中。这就是为什么我用\b边界的意义所在加上边界之后6位数字的头尾都不满足“前后是非单词字符”的条件所以不会从中间开刀。3.2 从0x到0X大小写风格与后续整理给数字加完0x前缀第一件让人纠结的事来了风格不统一。有的人喜欢小写0x有的人习惯大写0X还有的代码规范要求十六进制里的字母必须大写。我见过太多团队为这事在代码评审里吵来吵去。从技术上讲大小写转换很简单。在加前缀步骤之前先单独做一轮大小写统一用查找目标[a-f]、替换为\U$0可以把所有小写字母转成大写。注意这里\U是Notepad支持的替换大小写转义符不是所有编辑器都有这个功能。想转小写就用\L$0。实际执行时我的建议是先统一数字内部的字母大小写再加0x前缀最后再来统一前缀本身的大小写风格。顺序错了会很别扭比如先加了0x再对大写字母做\U操作会把0x里的x也转成大写最终效果虽然没什么原则性问题但容易造成二次污染。我习惯把最终格式定为全小写0xa1b2这符合GCC、Clang等主流工具链的默认输出风格也方便和大多数开源项目的代码风格保持一致。如果团队规范要求大写那就全部大写只要保证一致就行。这里还有一个冷知识在C语言里0XFF和0xFF完全等价前缀大小写不影响数值源码里纯粹是风格问题。但在Python里0XFF也是合法的所以不用纠结兼容性。3.3 自动补零、对齐位宽与去多余空白加前缀的需求往往伴随着格式化需求。比如你有一列两位的十六进制数1 A FF你想把它们统一成0x01、0x0A、0xFF也就是高位补零。这个需求用正则替换也能做但要分两步第一步先把单位数命中替换为0x0$0第二步再对已经是两位数的加前缀。比如查找目标\b[0-9A-Fa-f]{1}\b替换为0x0$0但这里有个安全隐患如果你文件里混着1到9的十进制数字也会被一并补成0x01到0x09。所以更好的做法是在加前缀之前就把所有数值统一成固定位宽这个需要用列编辑模式或者插件功能纯正则反而容易绕晕。说到列编辑这里补充一个实用技巧如果数据本身就是整齐的表格结构用Alt鼠标拖拽进入列编辑模式直接在某列的开头输入0x可以用列模式一次性给整列加上相同前缀。这种方法要比正则快得多而且根本没有误匹配风险。但它的适用条件也苛刻数据必须是规则的、对齐的每个数字起始列位置一致。所以正确思路是列编辑解决“规则数据”正则解决“不规则数据”两者互为补充没有哪个能包打天下。另外替换完成后的空白整理也很常见。比如一行的数据多到超出屏幕宽度你可以用“编辑 空白操作 去除行尾空格”或者用正则把多个连续空格压成一个查找目标{2,}两个及以上空格替换为 单个空格如果是想给每个数字后面统一加逗号、换行那又是另一套正则了我会在下一节的综合案例里演示。4. 常见问题与实战排查到这一步你大概率已经能处理八成以上的加前缀需求了。但剩下那两成才是真正浪费时间的地方。我把这几年用过、踩过、帮别人排查过的典型问题整理成一张速查表再配合几个真实场景讲一讲排查思路希望能帮你少走点弯路。4.1 问题速查表现象常见原因解决方案替换后出现0x0x原文里有些数字已经有0x前缀规则没有排除先搜0x[0-9A-Fa-f]并把它们换成临时占位符再执行加前缀最后恢复大小写字母A-F被漏掉正则里只写了[0-9]没包括A-F改用[0-9A-Fa-f]作为字符集合普通十进制数字被误加0x数据中混有123这类十进制数规则没加位宽限制用\b[0-9A-Fa-f]{1,2}\b限制长度或先用其他规则排除负数-1被匹配成0x-1负号不在匹配范围内\b把负号当作边界先用规则把负号处理掉或改用断言排除负号场景REG1_ADDR里的1被加了0x下划线是单词字符\b边界判断失误用(?![0-9A-Fa-f_])和(?![0-9A-Fa-f_])替代\b一次替换只改了最后一段正则引擎在匹配时默认贪婪遇到重叠时跳过了检查量词和*的行为必要时用{m,n}精确限定替换后字母大小写混乱数据本身大小写混写且规则没统一先用\U或\L统一大小写再加前缀这张表里的“解决方案”看起来都不复杂但难就难在你遇到问题的那一刻能不能想到。我的建议是别硬背正则把你的数据和期望结果放在一起做对照逐条检查边界条件这样思路会清晰很多。4.2 那些年踩过的坑这里分享几个我亲历过的“惨案”希望能给你提个醒。第一坑忘了排除已经带0x的数。有次我把一整份带注释的驱动代码里所有十六进制数字加前缀结果大量原本写着0xFF的地方变成了0x0xFF整个文件直接废掉。从那以后我的“加前缀”规则默认先排除已有前缀的数据处理完再恢复回来顺序是临时占位、加前缀、还原。这个流程虽然多两步但稳如老狗。第二坑忽略了A-F以外的十六进制字母。严格来说十六进制数字只包含0-9和A-F/a-f。但有些调试工具导出的数据里会带H后缀比如0AFH这是某些汇编器的表示法。如果你拿[0-9A-Fa-f]去匹H会被排除替换出来的结果就是0x0AF后面孤零零挂个H编译直接报错。这种格式兼容问题只能在替换前先做好数据清洗或者专门写一套针对该格式的规则。第三坑替换范围没选对。Notepad的“全部替换”默认作用域是整个文件不是当前选区。如果你只想处理某一段一定要勾选“选区内替换”否则一按下去全文件遭殃。这个坑我犯过不止一次现在养成条件反射了先选中目标范围再操作。第四坑正则里用反斜杠习惯性的复制粘贴。不同编辑器的正则引擎有细微差异。Notepad默认使用的是PCRE风格的引擎它支持$0这种引用方式换成其他编辑器有的用\1有的用$复制粘贴的时候如果不了解差异很容易出现“在A工具里好好的到B工具里全乱”的情况。所以当你从网上复制正则的时候先弄清楚目标编辑器的语法风格再下手。4.3 更复杂的场景留一手最后聊几个工作中更复杂的场景权当做个思维发散。场景一数据是地址区间比如1000-100F你想把它变成0x1000-0x100F。这里面的难点是-连字符既是数学符号又是范围分隔符直接套用前面的正则会把1000和100F都加上0x结果还行但要注意连字符两侧的空格问题。如果格式是1000 - 100F就得更细致地处理空白。场景二同一行既有二进制数字又有十六进制比如1010B 3F H。这类混合格式在指令集描述文件里很常见你需要先识别出哪些是十六进制、哪些是二进制再分别处理。单纯的[0-9A-Fa-f]会把二进制的1010也当成十六进制这是最容易搞混的。场景三CSV文件里的十六进制列。如果你的数据是从Excel导出的带分隔符格式替换时要注意逗号、引号等符号和\b的相互影响。我的做法是先不改任何东西直接搜一遍目标格式的中括号里定义的字符集合看一眼命中了多少处再决定替换规则。场景四超大数据量。如果文件达到几十MB几千行正则替换的性能就开始有感知了。Notepad处理这种规模依然可以胜任但执行“全部替换”时会有短暂卡顿。这时候正确的思路不是忍着而是先把数据分块处理或者先删除无关内容把要改的部分单独保存成一个小文件处理完再合并回去。反正核心思想就是能让工具少干活就少干活正则也讲究一个“够用就好”。5. 从一次替换到工作流让操作沉淀为肌肉记忆写了这么多其实最想传达的不只是一条正则规则而是一种处理文本的思路。那如果你觉得“每次都手打正则太累了”我还有一个小建议把常用的替换规则存成Notepad的宏。录制宏就是把一次替换操作记下来下次一键执行。录制的过程中有一点要注意宏会记录你点击按钮的坐标和操作顺序但不会记录你输入的查找目标和替换文本之间的变化。也就是说如果你的目标是固定模式、固定替换文本那宏非常合适如果你的目标每次都不一样宏就没什么优势反而会把你带入“上一个能用的正则”的思维定式里。我更常做的是把规则记在头脑里看到一个需求先判断数据类型再判断边界条件最后选择正则规则。这个过程一旦熟练处理速度是非常快的。有一次同事拿了一份两百行的寄存器配置表找我说急用我当着他的面用三条正则加起来不到三十秒就把一份带缩进、带逗号、带0x前缀、大小写统一的配置表生成了出来。他吃惊地问“怎么做到的”我说这就是正则替换的基本功你花二十分钟学一下以后每天都用得着。说实话类似“加0x前缀”这种需求在很多人看来就是个不起眼的小事根本不值得写篇文章。但恰恰是这种小事的处理效率决定了你每天能省下多少时间、能少犯多少低级错误。工具就摆在那里会不会用、用得顺不顺手完全是另一回事。希望这篇文章不只是给你一个可以直接复制的替换规则更能让你体会到“先想清楚边界条件、再做批量操作”的做事方法。下次再遇到类似的格式化问题你至少知道该从哪儿下手了。