找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 2324|回复: 47

[发布] [26-8-2] binmay 灵活掩码版,搜索替换命令工具

  [复制链接]
发表于 2026-6-30 17:50:56 | 显示全部楼层 |阅读模式
本帖最后由 2010hook 于 2026-8-3 20:48 编辑

原作者:Sean Loaring,Slore
原地址:https://github.com/slorelee/binmay

Binmay 是用于文件或流中搜索替换进制字符串的命令行工具,更通用。

2026-07-06_190806.png

近期,DeepSeek 编程能力增强了,我令其以 资深编程专家角色 经几十次深度优化源码,结果喜人。

2026-8-02 更新:优化了编程提示词,提高了代码质量,消灭了一些潜在bug。增加 32bit.exe
2026-7-30 更新:性能、安全提升。防止全通配掩码替换死循环;64位匹配计数,适合处理GB级大文件。
2026-7-24 更新:改用MinGW编译,提高性能和可靠性,修正警告的3处代码写法。
2026-7-09 更新:新增灵活支持掩码 ?? .. 以及 忽略/匹配索引语法。
2026-6-30 发布:binmay2 修复原版所有bug,优化架构,增强性能。

---
MinGW 编译参数:
gcc -std=c17 -O2 -flto -pipe -fstack-protector-strong -D_FORTIFY_SOURCE=2 -Wall -Wextra -Wpedantic -Wconversion -Wsign-conversion -Wl,--nxcompat,--dynamicbase,--gc-sections -ffunction-sections -static -s %src_list%

binmay.7z (50.6 KB, 下载次数: 115)
-------------------------------------------------------

最新版相对原始代码近乎重写级别的深度优化,在保持原有设计思想的基础上,修复了大量隐性缺陷,大幅提升了健壮性、性能、可移植性以及可维护性。

1. 编译与可移植性

  • 原始代码: `f_malloc` 中错误地强制转换为未定义 `(struct input*)`
    优化版本: 完全移除无意义的转换,使用统一的 `xmalloc`,返回 `void*`
    改进意义: 消除编译错误与未定义行为,并实现 Windows / Linux 跨平台编译

  • 原始代码: 未处理 Windows 文本模式可能导致 `\n` → `\r\n` 转换,破坏二进制数据
    优化版本: 引入 `set_binary_mode()` 函数,对 `stdin/stdout/stderr` 设置 `O_BINARY` 模式
    改进意义: 保证二进制数据在 Windows 下正确读写

  • 原始代码: 自定义 `getopt` 存在状态机 bug,且返回 `-1` 非标准
    优化版本: 保留自定义 `getopt`,但修复了错误返回逻辑(统一 `return '?'`),并增强错误信息
    改进意义: 命令行解析更健壮,行为更符合预期


2. 内存管理与资源泄漏

  • 原始代码: 全局变量泛滥(`verbose`、`matches`、`pukebuf`、`plen` 等),资源释放困难
    优化版本: 所有配置集中到动态分配的 `struct app_config`,通过指针传递,`main` 末尾统一 `free`
    改进意义: 消除全局状态,生命周期清晰,易于测试和复用

  • 原始代码: 所有通过 `f_malloc` 分配的句柄、缓冲区、掩码结构从未释放,内存泄漏
    优化版本: 实现完备的 `*_free` 系列函数,`main` 采用 `goto` 清理链,无论成功或失败路径均释放所有资源
    改进意义: 彻底解决内存泄漏问题,运行更稳定,处理大量文件不会耗尽内存

  • 原始代码: 缓冲区固定 1024 字节(`BUF_LEN`),且 `masked_string_setstr` 上游长度检查对 `u:` 格式无效
    优化版本: 缓冲区扩大至 `IO_LEN = 128 * 1024`(128KB),大幅减少 I/O 次数;长度检查前置至 `process_string_default` 内部,杜绝越界
    改进意义: 提高吞吐量,根除缓冲区溢出隐患


3. 错误处理与健壮性

  • 原始代码: 多数函数内部直接 `exit(1)` 或 `abort()`,无法优雅恢复,且资源泄露
    优化版本: 所有函数返回错误码或 `LEN_UNSET`,错误层层上传,`main` 统一处理并跳转清理
    改进意义: 资源始终得到释放,错误处理路径完整可靠

  • 原始代码: `fwrite` 未处理短写(short write),大数据量下可能写入不完整
    优化版本: 实现 `fwrite_all`,循环写入直到全部字节发送完毕
    改进意义: 确保大数据块完整写入,避免数据损坏

  • 原始代码: `-u/-U` 原地更新极不安全:直接 `rename` 原文件后打开原文件名写入,若程序崩溃则数据不可恢复
    优化版本: 采用临时文件 + 原子重命名模式:通过 `mkstemp`/`_mktemp_s` 创建安全临时文件,所有输出写入临时文件,成功后才执行重命名;失败时保留临时文件并给出明确恢复提示;若已备份`*.0rg`则不覆盖,保留初始版本
    改进意义: 零数据丢失风险,数据完整性得到保障

  • 原始代码: 掩码长度不一致时仅警告并截断,可能产生非预期结果
    优化版本: 严格校验掩码长度与字符串长度必须相等,否则报错退出
    改进意义: 避免静默执行错误操作

  • 原始代码: 空搜索字符串或非法前缀无检查
    优化版本: 增加 `search->length == 0` 检查,非法前缀明确返回错误
    改进意义: 提早暴露参数错误,避免无意义运行

  • 原始代码: `buffered_skip` 中偏移量 `coffset` 为 `int`,可能溢出
    优化版本: `coffset` 改为 `long long`,并在跳过前检查溢出
    改进意义: 支持超过 2GB 文件的处理,无符号溢出风险


4. 搜索算法性能飞跃

  • 原始代码: `masked_string_seek` 对每个位置无差别调用 `masked_string_match`(朴素 O(n*m) 匹配)
    优化版本: 引入快速跳跃过滤:预计算前两个非通配字节位置及末尾非通配字节,先检查这三个关键字节,不匹配则立即跳过;只有通过快速筛选后才执行完整掩码匹配
    改进意义: 对含大量通配符的掩码(如仅固定首尾字节),无效概率仅有1/16M,性能提升一个数量级

  • 原始代码: 缓冲区大小为 2KB,搜索时滑动窗口小,频繁 I/O
    优化版本: 缓冲区提升至 256KB(`IO_LEN * 2`),单次读入更多数据,大幅减少系统调用
    改进意义: I/O 次数锐减,整体吞吐量显著提高


5. 掩码功能创意增强

  • 原始代码: 掩码只能通过 `-S`/`-R` 指定十六进制字节序列(如 `00ff`),表达能力有限
    优化版本: 新增三种掩码语法(中文使用手册有详细说明示例):
    • 正常模式:保留原有十六进制对,同时支持 `??` 或 `..` 作为通配符(对应掩码字节 0x00)
    • 忽略列表 `!`:如 `!0,2-4`,表示仅忽略指定字节,其余字节必须完全匹配
    • 匹配列表 `=`:如 `=0,2-4`,表示仅匹配指定字节,其余字节忽略。并实现索引列表的范围(`-`)和逗号分隔解析
    改进意义: 极大提升二进制补丁的便捷性,可灵活选择“关注/忽略”任意字节位置
    常见 ?? 和 .. 属于Byte级,会忽略256种可能组合,并非高大上。索引列表的价值更大。
    十六进制 0~F (16x16种组合) 才是精确匹配bit,须用二进制推导!掩码底层是二进制,0 表示忽略,1 表示匹配。


  • 原始代码: 无全通配掩码检查,设置全为 0x00 的掩码会永远匹配但毫无意义
    优化版本: 检测掩码是否全部为 0(全通配),并报错拒绝
    改进意义: 防止意外误用,操作意图更清晰


6. 代码架构与可读性

  • 原始代码: `DEBUG` 宏混在代码中,大量无用原型声明(如 `open_outfile`)存在
    优化版本: 彻底清除冗余代码,所有内部函数使用 `static` 限制作用域
    改进意义: 代码精简,命名空间干净,避免意外冲突

  • 原始代码: 函数定义分散,混杂在大量注释括号 `{{ }}` 中,风格老旧
    优化版本: 采用现代 C 风格,清晰划分“数据结构 → 前向声明 → 实现”模块,简洁明了
    改进意义: 可读性和可维护性大幅提升

  • 原始代码: `main` 文件打开、参数解析、搜索、puke 的逻辑纠缠在一起
    优化版本: 将参数解析抽离为 `parse_args`,原地更新逻辑独立处理,`main` 仅负责流程调度和清理
    改进意义: 职责分离,便于扩展和调试

  • 原始代码: 返回匹配数量使用全局变量 `matches`
    优化版本: 改为 `do_search_replace` 返回 `long long`,同时支持 64 位大文件统计
    改进意义: 无状态函数,可重入,并支持海量匹配

  • 原始代码: `hexdumpline` 输出无分隔符,可读性差
    优化版本: 格式化输出为空格分隔的十六进制对(`printf("%s%02x", i?" ":"", byte)`)
    改进意义: 输出结果更符合常见 hexdump 习惯,便于阅读和后续处理


7. 其他细节优化

  • `-u`/`-U` 备份后缀从 `.org` 改为 `.0rg`,减少混淆可能性,语义更明确。
  • 新增 `-b` 选项位置约束检查,要求其必须出现在 `-s`/`-r`/`-p` 之前,防止用户误用。
  • `-i`/`-o` 与 `-u`/`-U` 互斥检查,提前报错,避免冲突。
  • 缓冲区大小定义统一为 `IO_LEN`,使用 `LEN_UNSET` 宏代替 `-1` 传递给 `size_t`,避免符号比较陷阱。
  • 中文帮助信息详实全面,包含掩码新语法和多个完整示例,学习成本极低。


总结
从底层修复了原代码的编译错误、内存泄漏、全局状态污染、不安全文件操作等硬伤,并通过临时文件原子写、智能搜索加速、灵活掩码语法、跨平台二进制模式支持、完整错误恢复链等改进,将一个小巧但粗糙的工具提升到了工业生产级质量
发表于 2026-6-30 18:03:29 | 显示全部楼层
感谢分享,赞~
回复

使用道具 举报

发表于 2026-6-30 18:15:42 来自手机 | 显示全部楼层
感谢分享辛苦了
回复

使用道具 举报

发表于 2026-6-30 18:29:43 | 显示全部楼层
感谢分享
回复

使用道具 举报

发表于 2026-6-30 19:41:26 | 显示全部楼层
最近接触最多的是 dUP 的搜索替换功能。它可以使用 ?? 代表通配符,而且可以是间断的。
例如:以其他字节为依据,将 DD 替换为 XX
AA BB ?? DD ?? FF -> ?? ?? ?? XX ?? ??

点评

发出来给我试试  发表于 2026-6-30 20:01
回复

使用道具 举报

发表于 2026-6-30 19:45:56 | 显示全部楼层
功能强大的工具。
回复

使用道具 举报

发表于 2026-6-30 20:25:00 | 显示全部楼层
压缩包内的 binmay.exe 和 binmay2.exe
啥区别

点评

分别为原版和优化版。32位的谁还用?你也别整双版了  详情 回复 发表于 2026-6-30 22:58
回复

使用道具 举报

发表于 2026-6-30 20:26:21 | 显示全部楼层
另外编译的,都是64位版本,,是否也提供下32位版本的

点评

今天增加了 binmay2_32bit.exe  详情 回复 发表于 5 天前
回复

使用道具 举报

发表于 2026-6-30 20:33:29 来自手机 | 显示全部楼层
谢谢分享binmay 优化版,二进制搜索替换命令工具
回复

使用道具 举报

发表于 2026-6-30 20:49:57 | 显示全部楼层
本帖最后由 chishingchan 于 2026-6-30 20:53 编辑

7.png

搜索模式中的字符也可以用通配符 ?? 来代替!
替换模式中自动将搜索模式中相同的字节使用 ?? 来代替。
回复

使用道具 举报

发表于 2026-6-30 21:01:26 | 显示全部楼层
感谢分享
回复

使用道具 举报

 楼主| 发表于 2026-6-30 22:58:35 | 显示全部楼层
BEIKING 发表于 2026-6-30 20:25
压缩包内的 binmay.exe 和 binmay2.exe
啥区别

分别为原版和优化版。32位的谁还用?你也别整双版了

点评

是这样,我经常用批处理使用这工具修改文件,从通用性来说当然是集成32位的通用  详情 回复 发表于 2026-6-30 23:19
这个不能够绝对!现观还有 %99 软件都是同时支持双架构的,需要跟大势。  发表于 2026-6-30 23:16
回复

使用道具 举报

发表于 2026-6-30 22:59:51 | 显示全部楼层
整理得超用心,这份资源太实用了
回复

使用道具 举报

发表于 2026-6-30 23:19:07 | 显示全部楼层
2010hook 发表于 2026-6-30 22:58
分别为原版和优化版。32位的谁还用?你也别整双版了

是这样,我经常用批处理使用这工具修改文件,从通用性来说当然是集成32位的通用

点评

官网没有32bit编译器下载了,我找不到小型可用编译器,源码已经公开了,可自行编译。  详情 回复 发表于 2026-7-10 12:00
回复

使用道具 举报

发表于 2026-6-30 23:41:13 | 显示全部楼层
这款软件很实用,感谢楼主大大了
回复

使用道具 举报

发表于 2026-6-30 23:43:59 | 显示全部楼层
能使用命令行?
回复

使用道具 举报

发表于 2026-7-1 02:04:56 | 显示全部楼层
还没用过呢,尝尝鲜
回复

使用道具 举报

发表于 2026-7-1 07:13:43 | 显示全部楼层
支持发布,谢谢

评分

参与人数 1无忧币 +5 收起 理由
yyz2191958 + 5

查看全部评分

回复

使用道具 举报

发表于 2026-7-1 11:05:54 | 显示全部楼层
感谢楼主分享binmay 优化版!
回复

使用道具 举报

发表于 2026-7-1 21:14:21 | 显示全部楼层
哎呀,还有这么一个命令行下修改二进制文件的工具,现在才知道,惭愧啊。
回复

使用道具 举报

 楼主| 发表于 2026-7-4 16:10:26 | 显示全部楼层
忍不住发布完美版,聚焦于架构优雅性,无可挑剔。主要改进:

1. 配置结构体 `app_config` 聚拢所有选项,`parse_args()` 独立解析。
2. 统一错误码 `binmay_err` 枚举,所有函数返回明确错误类型。
3. 匹配回调机制:`do_search_replace` 不再混合替换/打印逻辑,而是接受回调,实现策略解耦。
4. 组合构造器 `masked_string_new_from()` 减少未初始化状态。
5. `main` 精简为清晰的流程控制。
回复

使用道具 举报

发表于 2026-7-5 03:13:28 | 显示全部楼层
一股逗包味道。。。

点评

我不用DB,你别DB  详情 回复 发表于 2026-7-5 06:26
回复

使用道具 举报

 楼主| 发表于 2026-7-5 06:26:21 | 显示全部楼层

我不用DB,你别DB
回复

使用道具 举报

发表于 2026-7-5 06:50:23 | 显示全部楼层
强大 谢谢
回复

使用道具 举报

发表于 2026-7-5 06:57:07 | 显示全部楼层
感谢分享
回复

使用道具 举报

发表于 2026-7-5 07:16:02 | 显示全部楼层
谢谢分享
回复

使用道具 举报

发表于 2026-7-5 08:19:42 | 显示全部楼层
谢谢分享
回复

使用道具 举报

 楼主| 发表于 2026-7-9 20:54:30 | 显示全部楼层
发布强大灵活的掩码版:
支持索引列表,! 和 = 解决了冗长十六进制掩码的痛点!
支持 ?? 和 .. 字节级掩码,原有Hex位掩码,共3种。
回复

使用道具 举报

发表于 2026-7-9 22:31:12 | 显示全部楼层
感谢分享
回复

使用道具 举报

 楼主| 发表于 2026-7-10 12:00:09 | 显示全部楼层
BEIKING 发表于 2026-6-30 23:19
是这样,我经常用批处理使用这工具修改文件,从通用性来说当然是集成32位的通用 ...

官网没有32bit编译器下载了,我找不到小型可用编译器,源码已经公开了,可自行编译。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1|闽公网安备35020302032614号 )

GMT+8, 2026-8-5 01:54

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表