☰
Ledger 复式记账系统版本演进深度解读:从 3.5.0 重大发布到 2.x 时代的完整技术脉络
2026/10/10 2:41:29 网站建设 项目流程
  • CLI

【免费下载链接】ledger

Double-entry accounting system with a command-line reporting interface

项目地址:https://gitcode.com/gh_mirrors/le/ledger
点击查看免费下载

Ledger 是一款以纯文本文件为输入、命令行报告为输出的复式记账系统。本文以仓库 NEWS.md 为主线,系统梳理 Ledger 从 1.6 到 3.5.0 的关键版本演进:重点剖析 3.5.0 在 C++17 现代化、FIFO/LIFO 批次匹配、报告性能优化、Python 绑定稳定性等方面带来的数百项变更,同时回顾历史版本引入的余额赋值、批次报告、价值表达式等至今仍在使用的基础能力。读完本文,你将掌握 Ledger 每个核心特性(批次、断言、自动交易、预算、查询语法)的引入版本、适用命令与底层实现依据,并能直接在当前仓库的源码与测试中验证这些能力。

一、3.5.0:一次里程碑式的重大发布

3.5.0 是 NEWS 中篇幅最大、信息量最密集的版本,累计合并超过 575 个 Pull Request。它系统性地完成了三件大事:现代化 C++ 代码库、大幅扩展测试覆盖(新增 419 个回归测试,源码覆盖率升至 89.6%,CI 覆盖门槛提升至 90%)、以及修复一批崩溃与正确性缺陷,同时新增了若干选项、指令与命令。

1.1 关键崩溃与安全修复

3.5.0 修复了长期困扰用户的若干崩溃类问题,主要集中在两个方向:

  • Python 绑定与嵌入式解释器:修复了journal.query()搭配--pivot、--account或-M等周期标志时的段错误(issues #1193、#1858)、Python 日志查询中的 use-after-free(#2152)、Python 持有 commodity 引用时close_journal_files()的段错误(#977、#978)、将 ledger 作为 Python 模块导入时的悬空 session 指针(#2163)、交互模式下ledger python重新初始化时的段错误,以及 Python 可选转换器中的栈破坏问题。这些修复与仓库中的 python/ 目录及 src/pyinterp.cc 的绑定实现直接对应。
  • 核心引擎空指针与迭代器失效:包括get_code()、post_pred(#1219)、apply指令函数(#1221)、magnitude()遇到空金额(#2212)的空指针解引用;source_context处理超大交易(#1838)、find_price在close_journal_files()后图索引失效、CSV--dc格式、--limit在--budget内过滤 commodity(#2247)、--gain --subtotal访问多币种账户(#965)、--sort date搭配桶账户(#3128)或余额报告(#3126)时的段错误等。

此外还修复了断言失败(如--payee-width=1时的truncate()、空表达式编译 #1899、alias()遇到已存在币种名、parse_posts中纯空白行、--trace与include指令交互)、数量标点剥离循环的缓冲区越界读取、--unround与--group-by的无限递归(#518)、自引用C(币种等价)指令导致的死循环(#1065),以及--invert在复合报告(#1908)和equity命令(#1645)下的行为修正。

1.2 C++17 代码现代化

3.5.0 将代码库迁移至 C++17,并用标准库替代多个 Boost 工具组件:

  • 编译器要求:GCC 8+、Clang 7+ 或 MSVC 19.14+,旧工具链将无法构建。
  • Boost 依赖瘦身:boost::filesystem、boost::any、boost::variant分别被std::filesystem、std::any、std::variant取代,boost::shared_ptr的使用大幅减少。find_package(Boost ...)现在只需date_time、iostreams、regex,可选python、nowide、unit_test_framework;最低 Boost 版本(1.72.0)不变。
  • 嵌入方注意:多数公开头文件现在使用std::optional、std::any、std::variant而非boost::对应物,下游显式命名 Boost 类型的代码需要一行 typedef 或全局替换。这一点可在 src/types.h、src/ledger.hh.in 等公共头中印证。
  • 全面采用 C++17 惯用法:结构化绑定(structured bindings)、if 语句初始化器、if constexpr、紧凑嵌套命名空间、inline static constexpr类常量、[[nodiscard]]与[[fallthrough]]属性,以及解析热路径上的std::string_view。
  • 资源管理:裸new/delete替换为make_shared/make_unique,BOOST_FOREACH替换为 range-for,throw()替换为noexcept。
  • 安全加固:修复了多处内存泄漏,以及getquote中当币种符号包含 shell 元字符时的命令注入向量。

二、3.5.0 核心功能纵览:按主题深入

2.1 商品价格、批次(Lots)与注解

自动 FIFO/LIFO 批次匹配(issue #164)是 3.5.0 最重要的记账功能:卖出不带显式{cost}注解的商品时,Ledger 可自动与未平仓批次配对,并根据匹配到的成本基础计算盈亏。新增--lots-fifo与--lots-lifo选项(隐含--lot-prices和--lot-dates),按时间顺序展示批次。仓库中的实现可见于 src/report.cc 的选项解析(OPT(lots_fifo)/OPT(lots_lifo))与 src/report.h,测试样例见 test/baseline/opt-lots-fifo.test:

2019-03-01 * Bought FOO early at high price Assets:Investments 2 FOO {180.00 EUR} [2019-03-01] Assets:Investments -360.00 EUR 2019-06-01 * Bought FOO later at low price Assets:Investments 1 FOO {150.00 EUR} [2019-06-01] Assets:Investments -150.00 EUR test bal assets:investments --lots-fifo 490.00 EUR 2 FOO {180.00 EUR} [2019/03/01] 1 FOO {150.00 EUR} [2019/06/01] Assets:Investments end test

批次注解的全面修复:在 commodity reduce/unreduce(#958)、带注解金额的余额断言、余额赋值以及print输出中保留批次注解;print中往返保留固定成本标记=(#1794);保留{{total}}批次价格记法;交易最终化时保留用户指定的批次日期;使用总成本记法时保留批次价格精度;从批次价格注解推导成本基础(#630);lot_price、lot_date、lot_tag允许零参数;--effective下批次注解使用生效日期。

价格与估值:新增--plopen(未平仓头寸的未实现损益)、--gain-since(相对周期收益计算);修复同日多条价格记录的未实现损益(#1821);由价格记录设定币种精度,后续交易可拓宽但不能收窄已记录精度(#1190、#2481);新增--decimal-places限制显示精度(#797);round()接受可选精度参数(#628);新增--round选项在聚合前逐笔舍入(#781)。P指令支持括号化表达式价格(#1101);pricedb 双向输出(#779);--latest加入prices/pricedb;D指令锁定币种显示格式(#1197)并允许单引号(')作为数字分组分隔符。此外还支持批量商品报价抓取(#588)、自定义估值选项--account-value-expr与--commodity-value-expr,以及capital_gain价值表达式变量。

2.2 余额断言(Balance Assertions)与余额赋值(Assignments)

  • 余额断言改为按日期而非文件顺序过滤;跳过 UUID 重复交易的断言;检查自动生成过账上的账户断言;--permissive下允许省略金额的余额赋值(#2005)。新增--check-in-file-order恢复 3.5 之前按文件顺序累加的行为(#3186),供依赖乱序日期条目排序的旧日志使用。
  • 修复仅含虚拟过账账户(#1699)、带引号币种(#904)、单价注解(#1125)、--decimal-comma(#1167)、零差值(#1168)等场景下的断言问题。
  • 余额赋值跨文件修复(#1831);print输出中余额赋值以= amount而非amount = amount呈现(#2100);--effective日期排序(#2071)。

2.3 报告与显示优化

register 命令性能优化:通过短路平凡amount表达式、利用strip(A+B) = strip(A)+strip(B)维护剥离后的运行总计、在无注解时从balance_t::strip_annotations提前返回,大日志(约 5 万过账)提速 46%(基准 6.0s → 3.3s)。这是 NEWS 中少有的量化性能数据,源自仓库 benchmark/ 目录维护的基准体系。

列表命令快路径:accounts、payees、tags、commodities命令改走stats快路径(#3202),只迭代过账流收集去重名称,不再负担 register/balance 的运行总计与舍入过滤器——在 2 万过账日志上这些命令原先比stats慢 6-10 倍;快路径仍尊重--limit、--period、--begin/--end、--pivot、--anon、--budget、--forecast-while、--group-by。

显示细节:多币种余额行对齐宽小数(#1795);-X激活时按换算值排序(#1556);父账户按家族总额排序(#723);--sort与--sort-xacts可同时使用;--flat模式下显示自身金额而非家族总额;Windows CMD/PowerShell 支持 ANSI 颜色(#2110);justify()计算宽度时忽略 ANSI 转义码。新增--append-format(#1740)、--ignore-diacritics(变音符不敏感搜索)、--pivot-only(以 pivot 值替换账户名,#1153)、--period-shift(平移周期边界,#954)、--group-by-cumulative(随时间累积的资产负债表)。

2.4 过滤、查询与聚合

3.5.0重写了查询解析器,将其实现为带文档化 EBNF 语法的递归下降解析器,语法定义发布在头文件中。仓库中 src/query.h 的lexer_t、parser_t、token_t即该实现的载体——词法器支持带引号模式('food'、"food"、/food/)、单字符运算符(@、#、%、=、&、|、!)与关键字(and、or、not、payee、code、expr等),并提供peek_token()/push_token()支撑递归下降;TOK_EQEQ(==)精确匹配元数据值(#842)、not用于print/xact/dump的位置查询(#1227)等行为均可在此找到对应 token。

查询相关修复还包括:--empty尊重查询/--limit谓词(#3189)、保留正则中的反斜杠转义、跨 REPL 命令保留 push 命令位置查询参数(#528)、运算符前尾随空白的词法处理、expr any()单参数查询(#1185)、CLI 查询参数中的账户别名展开、--pivot与命令行账户查询(#1154)/内置属性(#1048)/基于 tag 的分组(#1042)的组合、--group-by与--pivot组合丢失后续分组(#1034)、--depth与--effective/--flat交互、--only在calc_posts之后应用且不改变运行总计(#762)、周期报告按账户计算平均值(#1950)、间隔平均值锚定报告开始日期。

2.5 日期、周期与时间处理

  • --begin/--end/--now接受时间分量(#1696),解析器结构化检测日期时间并以@作为日期/时间分隔符。
  • 新增%m-%d内建短日期格式(#566);xact命令接受相对日期表达式(yesterday、tomorrow、tday、yday、tmrw,以及通过on <expr>的完整周期语法,#647);CSV posted 列支持aux/aux_date/auxdate别名。
  • --price-exp/--leeway/-Z接受时长单位(s、m、h、d、w,#607);明确--price-exp默认单位为小时(#1210);无显式年份的 begin 日期应用月份回退;-b MM/DD使用最近过去事件(#1095);支持LEDGER_INIT_FILE与LEDGER_INIT环境变量(#1189);Cygwin 下 Windows 路径展开(#1188);include指令识别 Windows 盘符路径(#1670)。
  • 修复-V -M在无交易周期的重估(#2131)、--monthly价格每周期显示最后价格(#583)、apply year指令结束时的year_directive_year恢复(#2413)、年份指令泄漏到xact/entry命令(#707)、包含文件处理后的年/纪元状态恢复(#1979)。

2.6 自动交易、预测与预算

  • 预测功能全面重构:预测现在包含--now所在周期而非仅输出严格未来周期;混合频率周期交易(如每月加每年)正确排序;未来from/since与过去until子句行为正确;--forecast-while被 balance 与 register 报告共同尊重;5 年安全上限在当前周期日期下不再下溢(关闭 #591、#1044、#1113、#1141、#1148、#1155、#1161、#1576、#1605 及崩溃 #2043)。
  • 新增payee-rewrite与account-rewrite指令(含对应 CLI 标志--payee-rewrite、--account-rewrite),在报告时对 payee 与账户名应用正则替换而不修改日志文件;另有指令可启用/禁用自动交易。
  • 自动交易账户名除$account外允许$expr;自动交易尊重生效日期;修复基于 payee 的Unknown账户解析;自动交易过账纳入--related输出(#993)。
  • 预算:无间隔的预算周期默认按月;预算处理前按日期排序过账(#590);带from子句的月度预算周期保留日序;周周期交易尊重开始日期;CSV 导入期间应用 payee UUID 映射;预注册内建元数据标签使--strict不再告警;抑制自动交易$account的虚假--strict警告(#545)。

2.7 CSV 转换、Timelog 与 Python 绑定

CSV:CSV 输出中剥离商品名的日志语法引号(#2008);转换期间设置解析上下文防止--strict下段错误(#2521);新增--csv-separator;修复带 code 时 CSV 标记、cost 字段处理(#1110)、缺失或同币种 cost 字段、CSVconvert的有符号借方金额;对缺日期列的 CSV 报清晰错误。

Timelog:新增--time-round将时长舍入到最近单位(#1608);datetime字段包含时间部分(#2264);timelog 条目应用 payee 子指令(#1211);timelog 自动关闭的未来签入错误(#1689);timeclock 交易与桶账户平衡;--time-colon算术修正;-X跨尺度单位换算时间值(#1177)。

Python 绑定:允许 ledger 作为 Python 扩展模块加载(#513,模块带可执行权限安装,#531);acprep新增--python-home与--python-version;xacts/posts可作为 Python 属性迭代(#682);xact.posts只返回原始过账(#2453);Commodity == string比较(#759);PostCollectorWrapper暴露display_amounts用于币种交换(#2158);修复FileInfo.filename/modtime(#1205);Session.read_journal()接受字符串路径;修复虚拟过账标志检测(#2169);ledger python退出后恢复终端设置(#774)。构建与用法可参考 README.md 的 "Python Bindings" 章节及 python/demo.py。

2.8 新指令、文档、构建与测试

新指令:payee-rewrite、account-rewrite、启用/禁用自动交易的指令;嵌套account声明(#877)与account指令上的元数据标签(#1681);=~运算符返回正则捕获组文本(扩展 #664)。

文档:手册大规模修订——重写 Value Expressions 章节并附完整语言参考与可运行 doctest(#804);新增税务年度分组--pivot、股票分红、销售税自动交易、tag 过滤等真实世界示例(#1117);修正单字母价值表达式变量(#994)与--price-db/--download(#1210)的过时文档;移除未实现的capture指令文档。

构建系统:默认分支从master切换为main;-DUSE_GPGME=ON时新增gpgmepp构建依赖;弃用 AppVeyor,改用 GitHub Actions MSYS2/UCRT64 Windows 构建(#1791),MSYS2/UCRT64 成为受支持的 Windows 工具链;新增 CPack.deb/.rpm打包器(make package);引入 clangd LSP、lintCMake 目标(clang-format/clang-tidy/cppcheck)与 lefthook 统一本地/CI 管道;--version输出显示构建类型;CMAKE_BUILD_TYPE由BOOL修正为STRING;更新捆绑 utfcpp 至 4.0.9;为 Nix 开发环境增加代码覆盖工具。

测试与覆盖:新增 419 个回归测试、覆盖率达 89.6%、CI 门槛升至 90%(#2832、#2728);为 153 个此前未覆盖的 open issue 添加回归测试(#3011);新增日志解析器的 libFuzzer harness(见 test/fuzz/journal_fuzzer.cc,CI 每晚运行);CI 矩阵加入 ASan/UBSan 消毒器构建与 Clang 性能回归检查;新增快照行为测试工具(见 test/snapshot.py);移除解析器 4096 字节行长度限制。

代码架构:将 src/textual.cc 按职责拆分为textual.cc、textual_directives.cc、textual_xacts.cc,共享 src/textual_internal.h;查询解析器重写为文档化递归下降实现;全代码库应用 clang-format 并在 CI 强制(#2499);fuzzer 在 boost::filesystem 迁移后改用std::filesystem。

三、3.4.x 与 3.3.x:稳定性与关键新特性

3.1 3.4.1 / 3.4.0

3.4.1 修复二进制版本号与优化构建下抛异常时的崩溃(#693)。3.4.0 的关键点:

  • 新特性:--hashes选项支持哈希链式交易完整性校验;基于基础币种的商品互换(commodity swaps);==~运算符提取正则捕获组(#664)——无捕获组时整体匹配作为字符串,有捕获组时产出序列(首个元素为整体匹配、随后为各捕获组,N 组则序列长度 N+1),不匹配返回false;--align-intervals报告选项;--lisp-date-format(#1206);yday作为 "yesterday" 快捷方式;嵌套account子指令(#877)使父账户声明子账户时无需重复完整冒号路径。
  • 修复:元数据校验段错误(#1800)、除零(#777/#2207)、regex_match()use-after-free、reg --related忽略桶交易(#2220)、calc后表达式上下文恢复(#2330/#2343)、apply year指令的闰年日期(#2468)、xact尊重最后一个 year 指令(#2413)。
  • Python:最低 Python 版本升至 3.9(要求 3.10 测试)、修复 Python 3.12 弃用警告、新增 commodityvalue_t与roundto绑定、移除 Python 2 测试支持。
  • 构建:升级 C++17、Boost 1.86.0(最低 1.72.0)、CMake 3.16.2;支持 Ubuntu 24.04 Noble;增加 readline 构建支持。
  • 文件处理:include指令跳过非法 UTF-8 文件名(#2421);自动交易在--pedantic下可创建账户(#2417);pricedb 输出确定性(#1783)。

3.2 3.3.x:环境变量、GPG 与 PAGER

3.3 系列引入多项实用能力:

  • $PAGER环境变量生效(#1674);include通配符按排序顺序包含匹配文件(#1659)、绝对路径化(#2075);优先尝试$XDG_HOME_CONFIG/ledger/ledgerrc或~/.config/ledger/ledgerrc。
  • 支持自动读取 GPG 加密文件(#1949);convert命令支持 "debit" 列(#1120);修复无行尾文件解析(#516)、-无空格表达式解析(#2001)、payee 元数据校验与 payee 别名(#556/#1892)、零差值过账被误判为空过账导致自动平衡(#1942);lisp 报告转义所有字符串值(#2034);quoted_rfc4180更名为quoted_rfc(函数名中的数字会混淆解析器,#2007);价值表达式函数名不再允许数字。
  • 3.3.1 修复format指令错误回归(#2205)、--version输出编译特性;3.3.2 修复除零(#777/#2207)并提高 src/unistring.h 断言中的字符串大小限制(#2174)。

四、3.2.x / 3.1.x:Python 3、价值函数与安全修复

4.1 3.2.0

  • Python 支持移植到 Python 3;--explicit因实体不再因属于已清算交易而被视为已定义而变为 no-op(#1819)。
  • 新增--average-lot-prices(批次均价)、%F日期格式说明符(#1775)、commodity_price(NAME, DATE)与set_commodity_price(NAME, DATE)函数。
  • --invert语义改为反转显示金额与总计而非金额本身(#1803)。
  • 3.2.1 回退三个回归提交(括号解析、--invert、价格注解文本比较性能),并允许指定 Python 版本(#1893)。

4.2 3.1.x:安全修复与生态完善

3.1.2 修复了多个安全漏洞,包括解析生效日期的 use-after-free(CVE-2017-2807)、延迟过账的 use-after-free(CVE-2017-2808)、选项解析栈溢出(CVE-2017-12481)、日期解析栈溢出(CVE-2017-12482);正则最大长度从 255 提升至 4095(#981);quoted_rfc4180提供 RFC 4180 合规引号 CSV 输出;--force-color不再要求--color(#1109);accounts命令支持--prepend-format。3.1.1 新增--no-revalued;Emacs Lisp 文件迁移至独立的 ledger-mode 仓库。

4.3 3.1:成本基础语义的修正

3.1 修正了成本基础的定义:发生收益/损失时保留原始成本基础——以 $10 买入 1 AAA、$12 卖出时,Ledger 此前会把 $12 当作成本,现在保留 $10 作为成本基础(解决资本收益/损失后-B的异常行为);不再为亏本/盈利卖出自动生成错误的Equity:Capital Gains/Equity:Capital Loss条目;支持虚拟过账成本;--permissive使余额断言静默;新增--no-pager、--no-aliases、--recursive-aliases;支持 payeeuuid指令;单过账状态标志(!/*)优先级高于整个交易状态。

五、3.0 与 2.x:奠定今日行为的基础特性

5.1 3.0:兼容性调整

  • 移除-g(--performance)选项。
  • 余额报告默认行为反转:3.0 中bal默认显示所有相关账户(即 2.x 的-s bal效果),需要 2.6 行为时使用bal -n;-s对余额报告不再有影响。

5.2 2.6.x:余额赋值与批次报告

2.6.1 引入"余额设定交易"(balance setting transactions)——这是至今仍被广泛使用的核心能力:

2008/07/27 Starting fresh Assets:Checking = $1,000.00 Equity:Opening Balances

若Assets:Checking已有余额,交易金额会被自动计算为使账户最终余额恰好为 $1,000.00。例如下面两笔与两笔显式金额完全等价:

2008/07/27 Starting fresh Assets:Checking $750.00 Equity:Opening Balances 2008/07/27 Starting fresh Assets:Checking = $1,000.00 Equity:Adjustments

等价于:

2008/07/27 Starting fresh Assets:Checking $750.00 Equity:Opening Balances 2008/07/27 Starting fresh Assets:Checking $250.00 Equity:Adjustments

多币种账户下,=只作用于匹配币种的部分余额;还可以在金额后追加= 目标余额形式(如$-20.00 = $60.00)同时指定金额与目标余额,若无法平衡则报 unbalanced 错误,可由Equity:Adjustments承担差额。

2.6.0.90 正式引入批次(lot)概念:商品可指定批次详情用于管理分组资产(如买卖股票)。经典示例——50 股 AAPL 以 $10 买入:

2007/01/14 Stock purchase Assets:Brokerage 50 AAPL @ $10 Assets:Brokerage

三个月后按价格卖出该批次($20/股),需显式标注成本{$10}并配平资本收益:

2007/04/14 Stock purchase Assets:Brokerage $1000.00 Assets:Brokerage -50 AAPL {$10} @ $20 Income:Capital Gains $-500.00

也可按日期与价格卖出({$10} [2007/01/14] @ $20)。批次定价报告选项在此版本定型,沿用至今:

选项作用
--lot-prices将不同批次价格的商品视为不同商品分别报告
--lot-dates按批次日期分离商品;使用@成本说明符的交易都有隐式批次日期与价格
--lot-tags按商品后(note)指定的任意备注标签分离
--lots使用全部批次信息分离商品

5.3 2.6:显示、谓词与表达式的完善

  • 长账户名省略样式重构:由"截断末尾"改为逐段缩写前缀(Expenses→Ex、Wednesday→We),必要时才从前端省略;样式可配置:--truncate leading|middle|trailing|abbrev与--abbrev-len 2。
  • 三种谓词的分工(至今仍是 Ledger 报告管线的核心概念):
    • --limit "a>100":计算阶段只纳入金额大于 100 的交易;
    • --only "a>100":发生在--limit与--display之间的二次过滤,只使用计算值大于 100 的交易——ledger -M --only "a>100" reg ^Expenses:Food只显示金额大于 100 的月份;
    • --display "a>100":只约束显示,运行总计仍包含全部交易——ledger --display "d>[this month]" reg Checking显示本月明细但保持正确期末余额。
    • 三者可组合:ledger -M --limit "a>20" --only "a>200" --display "year == yearof([last year])" reg ^Expenses:Food。
  • 新增--base(可换算币种以最基础形式报告,如 timeclock 秒数)、--ansi/--ansi-invert(运行总计列负值红色,由格式修饰符!触发,如%!12.80T)、--descend AMOUNT/--descend-if VALEXPR(下钻到汇总值背后的组成交易)、dump命令(ledger -f huge.dat -o huge.cache dump生成二进制缓存,加载约快六倍)。
  • 价值表达式语法定稿:相等用==;U/A/S函数要求括号参数;P恒为两参;支持逗号运算符与函数定义((f(x)=x*2,f(100))得 200);标识符可任意长,并提供长名称替代(m→now、a→amount、b→cost、d→date、O→total、v→market、g→gain等);新增parse/expr命令(前者在解析日志前、后者在解析后求值单一价值表达式)与--debug转储解析树;日志或初始化文件中可用@def foo(x)=x*1000定义价值表达式函数;新增min(x,y)/max(x,y)。

5.4 2.5 / 2.4 / 2.3 / 2.2:日期、别名与交互基础

  • 2.5:生效日期(effective dates)语法定型——2004/10/03=2004/09/30 Credit card company表示实际日期 10/03、生效日期 09/30,配合--effective报告;单过账也可标注日期([2004/10/10=2004/09/15]);新格式代码%d(有生效日期时输出ADATE=EDATE);register 可拆分不同日期的组成交易;单过账单独清算(* Liabilities:MasterCard);C//价值表达式正则匹配商品符号;移除 Python 集成(2.0 曾引入,3.2 重新回归)。
  • 2.4:-$100.00与$-100.00等价;交易内联数学($20.00 + $2.50);"catch all" 账户自动平衡(A Liabilities:MasterCard);单过账无金额条目在多币种下也总能平衡。
  • 2.3:!alias ALIAS = ACCOUNT指令;--version显示可选模块。
  • 2.2:D <COMM>指令(如D $1,000.00)设定默认币种及格式标志;二进制缓存记录价格历史数据库,LEDGER_PRICE_DB变化时自动重建;%S/%B/%E格式代码暴露来源路径与字符位置;pricesdb命令;output FILE命令;--reconcile BALANCE/--reconcile-date DATE对账选项;过账!(pending)标志;新价值表达式正则命令(c//代码、p//payee、w//短账户名、W//完整账户名、e//备注,如ledger -l e/{tax}/ reg)。
  • 2.0(全面重写,保留数据格式与命令行语法):引入价值表达式、复杂日期掩码、二进制缓存、xml报告(ledger xml rent | ledger -f - reg rent可回读)、命令后正则仅匹配账户名而--后匹配 payee(ledger register expenses -- john)、!account/!include/!end结构、基于价值表达式的自动交易(= VALUE-EXPR+ 交易体)、报告选项定型(-o/-O/-B/-V/-g/-G/-A/-D/-w/-p INTERVAL/-y DATEFMT/-M/-Y/-W/--dow/-P/-j/-J/--period-sort)、LEDGER_FILE/LEDGER/LEDGER_CACHE环境变量。
  • 1.6/1.7:1.7 引入价格历史与基于成本/市值的报告;1.6 可解析 timeclock 时间日志文件(商品单位为h)。

六、在仓库中验证与上手

  • 查看完整变更清单:NEWS.md 是逐版本变更的主文档;README.md 提供依赖表(CMake 3.16.2、Boost 1.72、GMP 6.1.2、MPFR 4.0.2、utfcpp 3.2.3)与快速构建入口(./acprep update,之后./ledger -f test/input/sample.dat reg运行首个命令)。
  • 验证新选项行为:test/baseline/ 目录按opt-*.test、func-*.test、cmd-*.test命名组织,如 opt-lots-fifo.test、opt-lots-lifo.test、opt-gain-since.test、opt-period-shift.test 等,可直接对照 3.5.0 新增选项的预期输出。
  • 深入实现:查询语法见 src/query.h(含 EBNF 文档与lexer_t/parser_t定义);选项分发见 src/report.cc(短选项别名解析,如-p下pivot/pivot_only_/plopen/period_shift_);文本解析按职责拆分在 src/textual.cc、src/textual_directives.cc、src/textual_xacts.cc。
  • 测试与覆盖工具:回归测试在 test/regress/(按 issue 编号命名,如1193.test对应journal.query()崩溃修复),快照工具为 test/snapshot.py,fuzzer 入口为 test/fuzz/journal_fuzzer.cc。

结语

从 1.6 的 timeclock 支持到 3.5.0 的 C++17 现代化与自动 FIFO/LIFO 批次匹配,NEWS.md 记录了一条清晰的能力演进曲线:数据格式与命令行语法保持稳定,而底层引擎持续现代化。对于使用者,理解--limit/--only/--display谓词分工、余额赋值=语义、批次注解与报告选项、价值表达式语法,是驾驭 Ledger 报告能力的关键;对于嵌入与开发者,3.5.0 的std::迁移、递归下降查询解析器与 90% 覆盖率门槛,则提供了现代 C++ 记账引擎的可读范本。所有上述特性都能在当前仓库的源码与测试中直接查阅与验证。

  • CLI

【免费下载链接】ledger

Double-entry accounting system with a command-line reporting interface

项目地址:https://gitcode.com/gh_mirrors/le/ledger
点击查看免费下载
上一篇:Apache RocketMQ 本地调试指南:在 IntelliJ IDEA 中启动 NameServer、Broker 与 Proxy
下一篇:pyvideotrans 内置 MOSS-Transcribe-Diarize 0.9B:端到端多说话人转写、说话人分离与时间戳对齐实战指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询