Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
d3aca67
feat(语言史): 《星号之下——语言史话》全书 35 篇 + 清欠账轮
oratis Aug 3, 2026
99e8d5c
chore(语言史): refresh_readme 看板回填实测字数
oratis Aug 3, 2026
fc2ad9b
chore(语言史): 清完 22 条记账类欠账 + 新增 refresh_words.py
oratis Aug 3, 2026
deae648
fix(语言史): 手工清账 40 条,含三处实质订正
oratis Aug 3, 2026
96b9216
fix(语言史): 手工清账收尾,609/749(81%)
oratis Aug 3, 2026
0dcacc9
fix(语言史): 成书前 71 条过一遍,人物谱与时间线批量补齐
oratis Aug 3, 2026
5f0ac07
feat(语言史): 九条全书体例拍板,写进规范 §六之二(27–35)
oratis Aug 3, 2026
ff74961
fix(语言史): 69 条待核过一遍,清到 673/749(90%)
oratis Aug 3, 2026
1cc8628
fix(语言史): 打通「下载原书」这条路,清到 678/749(91%)
oratis Aug 4, 2026
2f2e0d7
fix(语言史): 36 条再过一遍,清到 681/749(91%)
oratis Aug 4, 2026
2df148b
fix(语言史): 等 archive.org 期间清掉 4 条不依赖它的
oratis Aug 4, 2026
b9e14e0
fix(语言史): archive.org 恢复后攻下四条硬骨头,清到 687/749(92%)
oratis Aug 4, 2026
d552043
fix(语言史): 再清三条,清到 690/749(92%)
oratis Aug 4, 2026
80cc12d
fix(语言史): 全书核验,修掉第四次同名撞车
oratis Aug 4, 2026
2b7afeb
清账 707/749:ch5 批评①换源、ch29 四条反例逐条落地、补 11 处人物谱缺口
oratis Aug 4, 2026
e6714ad
清账 711/749:ch28 三条全清(含一处口径错误)、ch27 补 Gilbert 2006
oratis Aug 4, 2026
79411ec
清账 714/749:CBETA 把「世界」推到二世纪;库辛、本-耶胡达两条改口径
oratis Aug 4, 2026
19a3bc4
清账 715/749:ch23 取到 Laycock 1982 原文,改掉四处(含一处误系出处)
oratis Aug 4, 2026
215d3af
清账完成 718/749 · 待核归零:ch14 换用特劳特曼、ch30 撤一句负面断言
oratis Aug 4, 2026
fa0613b
docs(handoff): 记录第三班次——待核归零、四条新取件路线、两条新错误模式
oratis Aug 4, 2026
b9b3387
成书前 31 → 23:定下 §36 全书人口口径,并办掉八条只等主控拍板的
oratis Aug 4, 2026
116fe38
成书前 31 → 13;修掉两个工具 bug(README 总字数十轮没刷新、两处字数口径不一)
oratis Aug 4, 2026
f16915f
docs(handoff): 记录第三班次下半——成书前 31→13、§36 口径、两个工具 bug
oratis Aug 4, 2026
8fd7330
欠账清零 749/749:打通 Ethnologue,改正五处数字
oratis Aug 4, 2026
9e08e7b
merge: 并入 main(本分支的 语言史/ 取代 8 月 3 日那版初稿)
oratis Aug 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
287 changes: 281 additions & 6 deletions 语言史/HANDOFF.md

Large diffs are not rendered by default.

90 changes: 46 additions & 44 deletions 语言史/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,59 +70,61 @@

| 篇 | 字数 | 节 |
|---|---:|:--:|
| [序章 · 绵羊和马](序章-绵羊和马.md) | 4,674 | 5 |
| [1 · 禁止讨论的题目](第一卷-开口/01-禁止讨论的题目.md) | 6,501 | 5 |
| [2 · 一条下降的喉管](第一卷-开口/02-一条下降的喉管.md) | 6,499 | 5 |
| [3 · KE家族](第一卷-开口/03-KE家族.md) | 5,833 | 5 |
| [4 · 操场上诞生的语言](第一卷-开口/04-操场上诞生的语言.md) | 5,511 | 5 |
| [5 · 一只羊的账](第二卷-刻下/05-一只羊的账.md) | 5,172 | 5 |
| [6 · 四次从零开始](第二卷-刻下/06-四次从零开始.md) | 5,671 | 5 |
| [7 · 矿工的字母](第二卷-刻下/07-矿工的字母.md) | 6,112 | 5 |
| [8 · 破译者](第二卷-刻下/08-破译者.md) | 5,921 | 5 |
| [9 · 不肯变成字母的字](第二卷-刻下/09-不肯变成字母的字.md) | 6,499 | 5 |
| [10 · 加尔各答的法官](第三卷-认亲/10-加尔各答的法官.md) | 6,139 | 5 |
| [11 · 把p变成f的定律](第三卷-认亲/11-把p变成f的定律.md) | 5,798 | 5 |
| [12 · 一棵树还是一片水](第三卷-认亲/12-一棵树还是一片水.md) | 6,375 | 5 |
| [13 · 听不见的音](第三卷-认亲/13-听不见的音.md) | 5,718 | 5 |
| [14 · 雅利安人是怎么被造出来的](第三卷-认亲/14-雅利安人是怎么被造出来的.md) | 6,181 | 5 |
| [15 · 从冰岛到孟加拉](第四卷-分布/15-从冰岛到孟加拉.md) | 6,493 | 5 |
| [16 · 中古音的回声](第四卷-分布/16-中古音的回声.md) | 6,480 | 5 |
| [17 · 走廊里的语言](第四卷-分布/17-走廊里的语言.md) | 6,352 | 5 |
| [18 · 沙漠河谷与角](第四卷-分布/18-沙漠河谷与角.md) | 6,479 | 5 |
| [19 · 草原与森林](第四卷-分布/19-草原与森林.md) | 6,501 | 5 |
| [20 · 稻作的三条线](第四卷-分布/20-稻作的三条线.md) | 6,129 | 5 |
| [21 · 独木舟上的语言](第四卷-分布/21-独木舟上的语言.md) | 6,425 | 5 |
| [22 · 鼓与搭嘴音](第四卷-分布/22-鼓与搭嘴音.md) | 5,597 | 5 |
| [23 · 世界上最难的地方](第四卷-分布/23-世界上最难的地方.md) | 6,491 | 5 |
| [24 · 新大陆的舌头](第四卷-分布/24-新大陆的舌头.md) | 6,317 | 5 |
| [25 · 没有亲戚的语言](第四卷-分布/25-没有亲戚的语言.md) | 5,876 | 5 |
| [26 · 日内瓦的三堂课](第五卷-解剖/26-日内瓦的三堂课.md) | 5,325 | 5 |
| [27 · 爱斯基摩人的雪](第五卷-解剖/27-爱斯基摩人的雪.md) | 6,499 | 5 |
| [28 · 句法结构](第五卷-解剖/28-句法结构.md) | 6,502 | 5 |
| [29 · 一条河边的例外](第五卷-解剖/29-一条河边的例外.md) | 6,149 | 5 |
| [30 · 手上的语言和造出来的语言](第五卷-解剖/30-手上的语言和造出来的语言.md) | 6,481 | 5 |
| [31 · 每两周一个](第六卷-存亡/31-每两周一个.md) | 5,251 | 5 |
| [32 · 让死掉的语言开口](第六卷-存亡/32-让死掉的语言开口.md) | 6,487 | 5 |
| [33 · 机器读懂了吗](第六卷-存亡/33-机器读懂了吗.md) | 5,731 | 5 |
| [终章 · 星号的另一边](终章-星号的另一边.md) | 4,696 | 5 |

当前正文字数:约 **10,008 / 240,000**(提纲与细纲另计)。
| [序章 · 绵羊和马](序章-绵羊和马.md) | 4,859 | 5 |
| [1 · 禁止讨论的题目](第一卷-开口/01-禁止讨论的题目.md) | 6,714 | 5 |
| [2 · 一条下降的喉管](第一卷-开口/02-一条下降的喉管.md) | 7,002 | 5 |
| [3 · KE家族](第一卷-开口/03-KE家族.md) | 5,893 | 5 |
| [4 · 操场上诞生的语言](第一卷-开口/04-操场上诞生的语言.md) | 5,629 | 5 |
| [5 · 一只羊的账](第二卷-刻下/05-一只羊的账.md) | 5,445 | 5 |
| [6 · 四次从零开始](第二卷-刻下/06-四次从零开始.md) | 5,899 | 5 |
| [7 · 矿工的字母](第二卷-刻下/07-矿工的字母.md) | 6,517 | 5 |
| [8 · 破译者](第二卷-刻下/08-破译者.md) | 6,357 | 5 |
| [9 · 不肯变成字母的字](第二卷-刻下/09-不肯变成字母的字.md) | 6,552 | 5 |
| [10 · 加尔各答的法官](第三卷-认亲/10-加尔各答的法官.md) | 6,430 | 5 |
| [11 · 把p变成f的定律](第三卷-认亲/11-把p变成f的定律.md) | 5,994 | 5 |
| [12 · 一棵树还是一片水](第三卷-认亲/12-一棵树还是一片水.md) | 6,435 | 5 |
| [13 · 听不见的音](第三卷-认亲/13-听不见的音.md) | 5,879 | 5 |
| [14 · 雅利安人是怎么被造出来的](第三卷-认亲/14-雅利安人是怎么被造出来的.md) | 6,595 | 5 |
| [15 · 从冰岛到孟加拉](第四卷-分布/15-从冰岛到孟加拉.md) | 6,665 | 5 |
| [16 · 中古音的回声](第四卷-分布/16-中古音的回声.md) | 6,584 | 5 |
| [17 · 走廊里的语言](第四卷-分布/17-走廊里的语言.md) | 7,393 | 5 |
| [18 · 沙漠河谷与角](第四卷-分布/18-沙漠河谷与角.md) | 6,893 | 5 |
| [19 · 草原与森林](第四卷-分布/19-草原与森林.md) | 6,951 | 5 |
| [20 · 稻作的三条线](第四卷-分布/20-稻作的三条线.md) | 6,138 | 5 |
| [21 · 独木舟上的语言](第四卷-分布/21-独木舟上的语言.md) | 6,482 | 5 |
| [22 · 鼓与搭嘴音](第四卷-分布/22-鼓与搭嘴音.md) | 5,661 | 5 |
| [23 · 世界上最难的地方](第四卷-分布/23-世界上最难的地方.md) | 6,955 | 5 |
| [24 · 新大陆的舌头](第四卷-分布/24-新大陆的舌头.md) | 6,799 | 5 |
| [25 · 没有亲戚的语言](第四卷-分布/25-没有亲戚的语言.md) | 7,132 | 5 |
| [26 · 日内瓦的三堂课](第五卷-解剖/26-日内瓦的三堂课.md) | 5,508 | 5 |
| [27 · 爱斯基摩人的雪](第五卷-解剖/27-爱斯基摩人的雪.md) | 7,063 | 5 |
| [28 · 句法结构](第五卷-解剖/28-句法结构.md) | 7,581 | 5 |
| [29 · 一条河边的例外](第五卷-解剖/29-一条河边的例外.md) | 6,978 | 5 |
| [30 · 手上的语言和造出来的语言](第五卷-解剖/30-手上的语言和造出来的语言.md) | 7,196 | 5 |
| [31 · 每两周一个](第六卷-存亡/31-每两周一个.md) | 5,700 | 5 |
| [32 · 让死掉的语言开口](第六卷-存亡/32-让死掉的语言开口.md) | 6,908 | 5 |
| [33 · 机器读懂了吗](第六卷-存亡/33-机器读懂了吗.md) | 6,170 | 5 |
| [终章 · 星号的另一边](终章-星号的另一边.md) | 5,036 | 5 |

当前正文字数:约 **223,993 / 215,000**(提纲与细纲另计)。

**全部 35 篇初稿完成**(序章 + 第 1–33 章 + 终章),六卷全部落地。**并已过一轮逐篇审校**——三十五篇各派一位责任编辑对着[写作规范](提纲/写作规范.md) §七 的十五项清单逐条查、直接改稿,结果见[审校总报告](提纲/审校总报告.md)。[语系谱](提纲/语系谱.md)的按章销账表**十二行全部打勾**——世界上已确认的语系、主要语族与孤立语言,在书中都有位置。

---

## 待办(审校轮之后的实况
## 待办(2026-08-04 实况

**1. 十六篇低于 4 500 字下限。** 实测分布是 2 983–5 834 字,中位数约 4 300。**没有靠注水去够下限**——按[写作规范](提纲/写作规范.md) §22,低于下限的章要回头检查"是不是漏了纲",而不是补字
**1. 篇幅:低于下限的已经没有了,超上限的有十八篇。** 实测 4 761–7 581 字,中位数 6 517

已逐篇对过卷细纲,**纲里的要点没有遗漏**;这些章短,是因为它们的骨架本身就紧(第 10 章只有一个人一段话、终章按设计不铺陈)。**修订轮该做的是加密度**——补人物细节、补最小例子、补章间呼应,而不是加篇幅。最需要加密度的五篇:第 10、20、21、26、29 章
**这不是注水,是清账的直接结果**——增出来的字全部是限定词、双方并列与出处范围。[写作规范](提纲/写作规范.md) **§22 已写明**:清账期间补的限定词与出处不计入上限,下限 4 500 不变。**主编未拍板前不要为凑数删限定词**——为凑数删限定词,正是这本书自己反对的事

**2. 欠账 391 条,全部待核。** 跑 `python3 tools/debt_report.py` 看分章明细。**初稿阶段一条未清是预期状态**——本书的欠账条目多为"某数字需对 Ethnologue 第 29 版核""某轶事的史料层级",属于成稿后集中处理的类型。优先级最高的三类:
**2. 欠账 749 条:已清 749(100%),待核 0,成书前 0。**

- **全书统一数字**([写作规范](提纲/写作规范.md) §23 那六项)在定稿时重取一次,一处改、处处引
- **轶事的史料层级**:商博良"我拿到了"、克诺罗佐夫抢书、耶利内克那句话、知里幸惠完稿当夜——正文已按传说处理,但每一条都要注明来路
- **在世研究者的生年**:人物谱里标 `?` 的十来位
跑 `python3 tools/debt_report.py` 看分章明细。**两栏都是零**:凡是能查的都查完了,查不到的写明了走过哪些路线,剩下那批「定稿时重取」的也已在 2026-08-04 取到一手数据。

最后十三条原本全卡在 Ethnologue 第 29 版上(`curl` 与 WebFetch 一律 403)。**打通的办法是改用应用内的真浏览器**——`ethnologue.com` 与 `glottolog.org` 都能直取,拿到了「7,170 languages are in use today」原句、免费的家族浏览页各语系语言数、Ethnologue 200(2026 版)名单,以及 Glottolog 5.3 的 Top-level family 246 / Isolate 183。据此改正了六处数字(汉藏 463、亚非 391、印欧 456、爪哇语、濒危 44%、孤立语言 183),并修掉序章一处把两个数据库并排却未注明的口径违规。

**一条没糊弄过去的边界**:单语言的母语者数确在订阅墙后($480/年)。免费的 Ethnologue 200 只给 L1+L2 总数,按[写作规范](提纲/写作规范.md) **§36②** 不能与本书的母语者数并排比。本轮只把它当上界用——书里每一处母语者数都通过了上界检验。这一条原样写在各章欠账里,没有说成「已核实」。

**3. 两处体例待定**:外语词形的转写体例(IPA / 拉丁转写 / 原文并存)尚未统一;重构式所据方案(如上古音、原始印欧语)各章分别注明,成书前应在[参考资料](提纲/参考资料.md)集中登记。

Expand Down
13 changes: 8 additions & 5 deletions 语言史/tools/build_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
只依赖标准库。Markdown 转换器只覆盖本书实际用到的语法子集。
"""
import re, sys, os, glob, html, json
import os, sys
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
from measure import count_text

# ---------------------------------------------------------------- 文件收集

Expand Down Expand Up @@ -185,11 +188,12 @@ def parse(path):
for item in re.findall(r"^- \[([ x])\]\s*(.*?)(?=\n- \[|\n*\Z)", blk, flags=re.S | re.M):
debts.append((item[0] == "x", re.sub(r"\s+", " ", item[1]).strip()))
body = re.sub(r"<!--.*?-->", "", body, flags=re.S)
words = count_text(body) # 先数字数:章标题算正文,与 README/measure.count 同口径
body = re.sub(r"^\s*#\s+.*?\n", "", body, count=1) # 章标题由 chh 单独渲染,去掉正文里那份
return fm, body, debts
return fm, body, debts, words

def wc(body):
return len(re.sub(r"\s", "", body))
# 字数由 parse() 在去掉章标题之前算好,见 measure.count_text。
# **不要在这里另写一套数法**——2026-08-04 就是这样漏掉 Markdown 记号,与 README 差了 11 148 字。

# ---------------------------------------------------------------- 组装

Expand All @@ -203,8 +207,7 @@ def build(outpath):
era_now = None

for anchor, kind, era, title, path in items:
fm, body, debts = parse(path)
n = wc(body)
fm, body, debts, n = parse(path)
secs = len(re.findall(r"^## ", body, flags=re.M))
open_n = sum(1 for d, _ in debts if not d)
done_n = sum(1 for d, _ in debts if d)
Expand Down
13 changes: 12 additions & 1 deletion 语言史/tools/measure.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,19 @@ def body(path):
t = re.sub(r"<!--.*?-->", "", t, flags=re.S)
return re.sub(r"^---.*?\n---\n", "", t, flags=re.S)

def count_text(text):
"""同一口径,但接收正文字符串而非路径。

给已经自己读过文件、去过 frontmatter 与注释的调用者用(build_html.py 就是)。
**不要在别处另写一套数法**——2026-08-04 发现 build_html.py 正是这样漏掉了
Markdown 记号那一步,与 README 的总字数差了 11 148 字(234 920 对 223 772),
而这个差额恰好就是本文件开头记的那笔「全书合计近一万字」。
"""
return len(re.sub(r"\s", "", MARKS.sub("", text)))


def count(path):
return len(re.sub(r"\s", "", MARKS.sub("", body(path))))
return count_text(body(path))

def sections(path):
return len(re.findall(r"^## ", body(path), flags=re.M))
5 changes: 3 additions & 2 deletions 语言史/tools/refresh_readme.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ def chnum(p):
assert re.search(pat, readme), "看板表未匹配——README 结构变了,先看一眼"
new = re.sub(pat, table + "\n", readme, count=1)

new = re.sub(r"当前正文字数:约 \*\*[\d,\s]+ / [\d\s]+\*\*",
f"当前正文字数:约 **{tot:,} / {TARGET:,}**", new, count=1)
pat2 = r"当前正文字数:约 \*\*[\d,\s]+ / [\d,\s]+\*\*" # 目标数带千位逗号,[\d\s] 配不上
assert re.search(pat2, new), "总字数那一行未匹配——先看一眼 README 是不是被改过"
new = re.sub(pat2, f"当前正文字数:约 **{tot:,} / {TARGET:,}**", new, count=1)

open("README.md", "w", encoding="utf-8").write(new)
print(f"看板已刷新:{len([r for r in rows if r[1].count('|') > 2])} 篇,合计 {tot:,} 字(目标 {TARGET:,})")
31 changes: 31 additions & 0 deletions 语言史/tools/refresh_words.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*-
"""把各章 frontmatter 的 words: 回填为实测值。

审校轮与清欠账轮都只改正文、没人回填这个字段,而此前没有任何脚本会刷它——
2026-08-03 实测 35 篇里 16 篇对不上,最大差 1 241 字。
字数口径统一取 measure.count,与 style_audit / refresh_readme 同源。
"""
import re, glob, sys
from measure import count

def main():
files = sorted(p for p in glob.glob('**/*.md', recursive=True)
if not p.startswith('提纲') and '_manuscript' not in p
and 'HANDOFF' not in p and '_卷细纲' not in p and 'README' not in p)
changed = 0
for p in files:
t = open(p, encoding='utf-8').read()
m = re.search(r'^words:\s*(\d+)\s*$', t, re.M)
if not m:
print(f" ! {p} 无 words 字段"); continue
old, new = int(m.group(1)), count(p)
if old == new: continue
t = t[:m.start()] + f"words: {new}" + t[m.end():]
open(p, 'w', encoding='utf-8').write(t)
print(f" {p.split('/')[-1]:<30} {old:>6} → {new:<6} ({new-old:+})")
changed += 1
print(f"\n回填 {changed} 篇 / 共 {len(files)} 篇")
return 0

if __name__ == '__main__':
sys.exit(main())
90 changes: 90 additions & 0 deletions 语言史/tools/roster_check.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/env python3
"""人物谱覆盖检查。

规范 §19 要求:凡在正文点名的人,人物谱必须有条目。

以前的检查只比对各章 frontmatter 的 `people:` 字段,**查不出正文里点了名而
frontmatter 漏登的人**——2026-08-04 一次全书扫描就这样查出十一处(严实、金力、
本尼迪克特、马蒂索夫、涅夫斯基、勒博尔涅、蒂斯、萨弗兰、约翰逊、迈克尔·科、
米利塔列夫、波特曼、潘迪特、里利、居尔德曼、本顿)。本脚本改为直接扫正文。

判据:正文里以「中文名(拉丁原名…)」形式正式引入的,逐个对人物谱查。
拉丁原名命中原名列、或中文片段以某个谱内中文名结尾,即算已登记。

正则的左边界会连带抓进前面的上下文(「德国的雅各布·格林」),所以用「以谱内
名结尾」而不是等值比较。剩下的输出里语言名、文化名、机构名、地名占多数,
需人工过滤——脚本只负责把候选缩到几十条,不负责判断谁是人。

**已知盲区**:只认「中文名(拉丁原名)」这一种正式引入式。正文里直接写
「同行麦克埃尔哈农」而不括注原名的,本脚本查不出来(2026-08-04 即漏了这一位,
是改第 23 章时手工发现的)。要补这个洞,得有中文人名识别,代价远大于收益,
所以留成已知盲区,写在这里提醒下一个人。
"""
import re
import sys
from pathlib import Path

ROOT = Path(__file__).resolve().parent.parent


def roster_rows():
text = (ROOT / '提纲' / '人物谱.md').read_text(encoding='utf-8')
rows = []
for line in text.split('\n'):
if not line.startswith('|') or set(line) <= set('|- '):
continue
cells = [c.strip() for c in line.strip().strip('|').split('|')]
if len(cells) >= 2 and cells[0] != '中文名':
rows.append(cells)
return rows


def chapters():
paths = sorted(ROOT.glob('第*/*.md')) + sorted(ROOT.glob('序章*.md')) + sorted(ROOT.glob('终章*.md'))
return [p for p in paths if not p.name.startswith('_')]


def body(path):
t = path.read_text(encoding='utf-8')
t = re.sub(r'<!--.*?-->', '', t, flags=re.S) # 去欠账区块
t = re.sub(r'^---\n.*?\n---\n', '', t, flags=re.S) # 去 frontmatter
return t


INTRO = re.compile(r'([一-鿿·]{2,12})(([A-ZÀ-Þ][A-Za-zÀ-ÿ\.\'\- ]{2,45}?)\s*[,,))]')


def main():
rows = roster_rows()
cn = {r[0] for r in rows}
lat = {r[1].lower() for r in rows if r[1] not in ('—', '')}

dups = sorted(n for n in cn if sum(1 for r in rows if r[0] == n) > 1)
empty = [r[0] for r in rows if len(r) >= 4 and not r[3].strip()]

seen, hits = set(), []
for p in chapters():
for m in INTRO.finditer(body(p)):
frag, name = m.group(1), m.group(2).strip()
if name.lower() in lat or any(frag.endswith(c) for c in cn):
continue
if name in seen:
continue
seen.add(name)
hits.append((p.name, frag, name))

print(f'人物谱 {len(rows)} 条 · 重复中文名 {len(dups)} · 速写为空 {len(empty)}')
if dups:
print(' 重复:', '、'.join(dups))
if empty:
print(' 空速写:', '、'.join(empty))
print(f'\n正文正式引入而未登记的候选 {len(hits)} 条'
f'(语言/文化/机构/地名会混在里面,需人工过滤):')
for fname, frag, name in hits:
print(f' {fname[:12]:14s} …{frag:14s} ({name})')

return 1 if (dups or empty) else 0


if __name__ == '__main__':
sys.exit(main())
Loading
Loading