ledger设置循环交易

ledger设置循环交易

ledger-cli如何支持循环交易

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
**ledger-cli** 里,“循环交易” 一般是指一种定期重复发生的交易,比如每周/每月的工资、房租、水电费、转账等。
Ledger 本身并不会像记账软件那样自动生成未来的交易,但它有两种机制可以支持这种场景:

---

## **1. 用 `~` 定义周期性交易(Periodic Transactions)**

Ledger 的 journal 文件可以直接写定期规则,让它在报表时自动扩展出这些交易。
语法大致是:

```ledger
~ every month on the 5th
    Expenses:Rent               2000 CNY
    Assets:Bank:ICBC
```

### 常用的周期表达式

,* `~ monthly` / `~ every month` → 每月
,* `~ weekly` / `~ every week` → 每周
,* `~ daily` / `~ every day` → 每天
,* 可以指定日期:`~ every month on the 15th`
,* 可以指定范围:`~ weekly from 2025/01/01 until 2025/12/31`

例如:

```ledger
~ every week
    Expenses:运营商:中国联通    49.75 CNY
    Assets:Bank:工商银行
```

这个不会直接写入账本,只会在你运行报表命令时自动计算这些交易的总额。

---

## **2. 生成实际交易(Materializing Periodic Transactions)**

如果你想让循环交易“落地”成普通交易(方便将来修改或导出),可以用 Ledger 自带的扩展功能:

```bash
ledger -f ledger.dat print --period "from 2025/01/01 to 2025/12/31"
```

配合 `--actual` 可以生成真实交易而不是仅显示。

也可以用 **ledger-autoschedule**(第三方脚本)将周期交易展开为实际的交易条目存到文件里。

---

## **3. 注意事项**

,* 周期交易不会自动影响期初余额,因为它是计算时临时展开的。
,* 如果你的循环交易金额会变化(比如水费),那最好生成实际交易手动调整。
,* Ledger 的日期计算遵循 `boost::date_time` 规则,复杂的周期需要测试一下(例如“每月最后一天”要用 `on last day of month`)。

---

如果你愿意,我可以帮你写一个 **可以在 ledger-cli 里自动生成全年循环交易的脚本**,这样 journal 文件里就是全部真实交易而不是临时规则。这样你就可以和普通账目一起查询和编辑。

你是想要这种**脚本生成法**还是**\~ every week**这种原生 Ledger 周期规则?

问答1

问:

1
2
3
4
5
6
~/.../2025/05 $ ledger -f ledger.ledger bal -b 08/31
While parsing file "/data/data/com.termux/files/home/yenao_ledger.github.io/ledger/2025/05/ledger.ledger", line 1843:
While parsing periodic transaction:
> ~ every daily
Error: Unexpected date period token 'daily'
~/.../2025/05 $

答:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
你这个报错是因为 Ledger 的周期语法写错了。

`~ every daily` 不是合法写法,Ledger 期望的是:

,* `~ daily`(每天)
,* `~ weekly`(每周)
,* `~ monthly`(每月)
,* 或者 `~ every day` / `~ every week` / `~ every month`

,**所以改成这样就行:**

```ledger
~ daily
    Expenses:运营商:中国联通    49.75 CNY
    Assets:Bank:工商银行
```

或者:

```ledger
~ every day
    Expenses:运营商:中国联通    49.75 CNY
    Assets:Bank:工商银行
```

---

### 补充:一些合法写法

```ledger
~ every week
~ weekly
~ every month
~ monthly
~ every month on the 15th
~ weekly from 2025/01/01 until 2025/12/31
```

`every` 后面不能直接跟 `daily` 这种词,必须是 `day` / `week` / `month` 或用简写。

---

我还注意到你是在 `-b 08/31` 这种日期范围里跑的,如果用 periodic transaction,它只会在查询期间自动生成符合条件的虚拟交易,所以日期语法也要匹配你要看的范围。

如果你愿意,我可以帮你整理一个 **Ledger 周期交易合法语法速查表**,这样以后就不会踩坑了。
你要我直接写出来吗?

问答2

问:

1
2
3
4
5
6
~/.../2025/05 $ tail ledger.ledger -n 4

~ daily
    Assets:Bank:工商银行                      -49.75 CNY
    Expenses:运营商:中国联通
~/.../2025/05 $

答:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
我看出问题了――你已经写了 `~ daily` 的周期交易,但运行 `ledger bal` 时它没显示出来,是因为:

1. **Ledger 默认不展开 periodic transaction**
   周期交易(`~ daily` 这种)只是一个“规则”,Ledger 在报表里只有在**查询区间有符合条件的日期**时才会临时生成虚拟交易。

2. **你的命令少了 `--period` 或指定时间范围的方式**
   `-b 08/13` 只是设置**起始日期**,但 Ledger 只会在该日期或之后符合周期规则的日期里计算。
   如果今天是 8/13,`~ daily` 会从 8/13 开始每天都加一笔,但 `bal` 只显示累计余额,不会列出每一天的交易。

3. **Periodic transaction 默认不影响总余额(unless `--forecast`)**
   如果你想在余额中看到它的影响,需要加 `--forecast` 选项。

---

### 解决方法

#### 如果只是想让它在余额里生效

```bash
ledger -f ledger.ledger bal -b 2025/08/01 --forecast
```

`--forecast` 会把周期规则展开成未来的交易(直到你设定的结束日期)。

#### 如果想查看具体展开的交易

```bash
ledger -f ledger.ledger register --period "2025/08/01 to 2025/08/31" --forecast
```

#### 如果要生成实际交易到文件

```bash
ledger -f ledger.ledger print --forecast --period "2025/08/01 to 2025/08/31" > expanded.ledger
```

这样 `expanded.ledger` 里就是每天的那笔 49.75 CNY,跟普通交易一样。

---

?? 小结:

,* `~ daily` 不会自动在原文件变成多行交易,它只是规则。
,* `--forecast` 是让规则“生效”的关键。
,* 如果要真正存成普通交易,需要用 `print` 导出。

---

我可以帮你写一个 **自动生成全年循环交易并保存到原账本的命令**,这样以后不需要 `--forecast` 也能直接算余额。
你要我帮你做这个吗?这样 49.75 CNY 会真的每天出现在账本里。

问答3

问:

1
2
3
4
~/.../2025/05 $ ledger -f ledger.ledger bal -b 08/13 --forecast
While parsing option '--forecast'
Error: No argument provided for --forecast-while
~/.../2025/05 $

答:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
你这个报错是因为 **`--forecast` 在新版 ledger-cli 已经被改成 `--forecast-while`**,而且它不是单独开关,而是需要跟一个“条件表达式”。

也就是说,旧版本的:

```bash
ledger ... --forecast
```

在你这个版本里变成了:

```bash
ledger ... --forecast-while <EXPRESSION>
```

---

## 用法示例

比如你想让它一直生成交易直到 2025/08/31:

```bash
ledger -f ledger.ledger bal \
    -b 2025/08/01 \
    --forecast-while "date <= [2025-08-31]"
```

这样 ledger 会展开 `~ daily` 规则,从 8/1 到 8/31 每天一笔。

如果想看具体的交易明细而不是余额:

```bash
ledger -f ledger.ledger register \
    --forecast-while "date <= [2025-08-31]"
```

---

## 解释

,* `--forecast-while` 会不断展开 periodic transactions,直到条件不成立。
,* 条件里可以用 `date`(交易日期)、`amount` 等 ledger 表达式。
,* 日期要用方括号 `[YYYY-MM-DD]`,这样它会被当成日期而不是字符串。

---

我可以帮你写一个命令,直接**展开全年循环交易并保存到新的 ledger 文件**,这样你就不需要每次都加 `--forecast-while` 了。
这样要做吗?这样你 ledger 文件里就有真实的每天交易记录了。
Licensed under CC BY-NC-SA 4.0
最后更新于 Aug 13, 2025 18:04 +0800
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计