Obsidian圣经经文范围链接Python脚本问题排查与优化需求
圣经经文范围链接生成脚本问题排查与优化
需求说明
在Obsidian中管理圣经笔记时,单节经文的链接功能正常,但需要实现多节经文范围的链接生成:
- 识别经文引用中的
-(范围)或+(零散节)符号,将范围内的每节经文生成为独立的嵌入链接 - 忽略非经文链接(如
[[The Great Controversy]]) - 生成以原经文引用命名的新文件,里面包含对应每节的嵌入链接列表
示例1
输入文本中的经文链接:[[Gen 1:1-4]]
生成的Gen 1:1-4.md内容:
![[Gen 1#1|Gen 1:1]] ![[Gen 1#2|Gen 1:2]] ![[Gen 1#3|Gen 1:3]] ![[Gen 1#4|Gen 1:4]]
示例2
输入文本中的经文链接:[[Gen 1:1-2+5]]
生成的Gen 1:1-2+5.md内容:
![[Gen 1#1|Gen 1:1]] ![[Gen 1#2|Gen 1:2]] ![[Gen 1#5|Gen 1:5]]
现有脚本无任何输出(无报错、无打印、无写入),且仅支持有限数量的-和+符号,需要排查问题并优化。
现有脚本代码
import os import re from itertools import groupby efile = "Scripture reference test.md" tfile = "srtemp.md" dirName = '/private/var/mobile/Library/Mobile Documents/iCloud~md~obsidian/Documents/Obsidian-vault/The Bible (KJV)'; chRefs = ["Gen ", "Exod ", "Lev ", "Num ", "Deut ", "Josh ", "Judg ", "Ruth ", "1Sam ", "2Sam ", "1Kings ", "2Kings ", "1Chron ", "2Chron ", "Ezr ", "Neh ", "Esth ", "Job ", "Ps ", "Prov ", "Eccless ", "Song ", "Isa ", "Jer ", "Lam ", "Ezek ", "Dan ", "Hos ", "Joel ", "Amos ", "Obad ", "Jonah ", "Micah ", "Nah ", "Hab ", "Zeph ", "Hag ", "Zech ", "Mal ", "Matt ", "Mark ", "Luke ", "John ", "Acts ", "Rom ", "1Cor ", "2Cor ", "Gal ", "Ephes ", "Phil ", "Col ", "1Thess ", "2Thess ", "1Tim ", "2Tim ", "Phil ", "Heb ", "James ", "1Pet ", "2Pet ", "1John ", "2John ", "3John ", "Jude ", "Rev "] #for chRef in chRefs: #pass #check for referrences: def rangeInt(): with open(tfile, 'w') as wf: with open(efile, 'r+') as ef: efl = ef.readlines() for line in efl: if any(chRef in line for chRef in chRefs): m = re.search('\[\[(.+?)]]', line) if m: foundRef = m.group(1) + "\n" ref = foundRef.split(' ') book = ref[0] rnumsL1 = ref[1] rnumsL1.split(':') chapter = rnumsL1[0] rnumsL2 = rnumsL1[1] if '-' in rnumsL2: if rnumsL2.find('-') < rnumsL2.find('+'): rnumsL2.split('-',1) firstVerse = rnumsL2[0] ad1 = rnumsL2[1] if '+' in rnumsL2: ad1.split('+',1) aP1 = ad1[1] if '-' in aP1: aP1.split('-',1) ad2 = aP1[1] sfv = aP1[0] else: lastVerse = aP1 else: lastVerse = ad1 elif rnumsL2.find('-') > rnumsL2.find('+') or '+' in rnumsL2 and '-' not in rnumsL2: #check this area if problem: ad1.split('+',1) secfv = ad1[1] if '-' in rnumsL3: ad1.split('-',1) aP1 = rnumsL3[1] else: lastVerse = ad1[1] else: lastVerse = rnumsL2[1] else: lastVerse = rnumsL2[0] def rangeConv(): if book != '' and chapter != '' and lastVerse > rnumsL2: if rnumsL2[1] != '': for n in foundRef: if n < lastVerse: print('![[' + book + ' ' + chapter + '#' + n + '|' + book + ' ' + chapter + ':' + n + ']]\n') wf.write('[[' + book + ' ' + chapter + '#' + n + '|' + book + ' ' + chapter + ':' + n + ']]\n') else: print('only one verse given') rangeConv() rangeInt()
问题排查
原脚本存在多个关键问题导致无输出:
split()方法未赋值:rnumsL1.split(':')等操作没有将结果赋值给变量,导致后续变量取值错误- 未定义变量:
rnumsL3未声明就直接使用,会触发隐式错误 - 嵌套函数作用域问题:
rangeConv定义在循环内部,且依赖外部变量,容易引发变量未初始化或作用域混乱 - 逻辑仅支持有限符号组合:硬编码判断
-和+的位置,无法处理任意数量的符号 - 循环逻辑错误:
for n in foundRef是遍历引用字符串的每个字符,而非遍历经文节数 - 条件判断错误:
lastVerse > rnumsL2是字符串比较,而非数字比较,逻辑不成立 - 未生成指定名称的文件:原脚本只写入临时文件
tfile,没有按要求生成以经文引用命名的文件
优化后的脚本
以下脚本修复了所有问题,支持任意数量的-和+符号,按需求生成对应文件:
import re import os # 配置参数 SOURCE_FILE = "Scripture reference test.md" VAULT_DIR = '/private/var/mobile/Library/Mobile Documents/iCloud~md~obsidian/Documents/Obsidian-vault/The Bible (KJV)' # 圣经卷册缩写列表(确保末尾有空格,匹配完整卷名) BOOK_ABBREVIATIONS = [ "Gen ", "Exod ", "Lev ", "Num ", "Deut ", "Josh ", "Judg ", "Ruth ", "1Sam ", "2Sam ", "1Kings ", "2Kings ", "1Chron ", "2Chron ", "Ezr ", "Neh ", "Esth ", "Job ", "Ps ", "Prov ", "Eccless ", "Song ", "Isa ", "Jer ", "Lam ", "Ezek ", "Dan ", "Hos ", "Joel ", "Amos ", "Obad ", "Jonah ", "Micah ", "Nah ", "Hab ", "Zeph ", "Hag ", "Zech ", "Mal ", "Matt ", "Mark ", "Luke ", "John ", "Acts ", "Rom ", "1Cor ", "2Cor ", "Gal ", "Ephes ", "Phil ", "Col ", "1Thess ", "2Thess ", "1Tim ", "2Tim ", "Heb ", "James ", "1Pet ", "2Pet ", "1John ", "2John ", "3John ", "Jude ", "Rev " ] def parse_scripture_reference(ref): """解析经文引用,返回(卷名, 章节, 节号列表)""" # 拆分卷名和章节-节号部分 book_part, rest = ref.split(' ', 1) chapter_part, verses_part = rest.split(':', 1) chapter = chapter_part.strip() # 处理节号部分:按+拆分各个片段 verse_segments = verses_part.split('+') verse_numbers = [] for seg in verse_segments: seg = seg.strip() if '-' in seg: # 处理范围:如1-4 start, end = seg.split('-') start_num = int(start.strip()) end_num = int(end.strip()) # 添加范围内所有节号 verse_numbers.extend(range(start_num, end_num + 1)) else: # 处理单节:如5 verse_numbers.append(int(seg.strip())) return book_part, chapter, verse_numbers def generate_obsidian_links(book, chapter, verses): """生成Obsidian嵌入链接列表""" links = [] for verse in verses: # 格式:![[Gen 1#1|Gen 1:1]] link = f'![[{book} {chapter}#{verse}|{book} {chapter}:{verse}]]' links.append(link) return '\n'.join(links) def process_file(): # 读取源文件内容 with open(SOURCE_FILE, 'r', encoding='utf-8') as f: content = f.read() # 匹配所有[[...]]链接 link_pattern = re.compile(r'\[\[(.+?)]]') all_links = link_pattern.findall(content) for link_text in all_links: # 判断是否是经文链接(匹配卷册缩写) if any(link_text.startswith(abbr.strip()) for abbr in BOOK_ABBREVIATIONS): try: # 解析经文引用 book, chapter, verses = parse_scripture_reference(link_text) # 生成嵌入链接内容 link_content = generate_obsidian_links(book, chapter, verses) # 生成目标文件名(用原引用作为文件名) target_file = os.path.join(VAULT_DIR, f'{link_text}.md') # 写入文件 with open(target_file, 'w', encoding='utf-8') as f: f.write(link_content) print(f"已生成文件: {target_file}") except Exception as e: print(f"处理引用 {link_text} 时出错: {str(e)}") if __name__ == "__main__": process_file()
优化点说明
- 正则匹配更精准:用正则提取所有
[[...]]链接,再通过卷册缩写筛选经文链接 - 模块化解析逻辑:
parse_scripture_reference函数专门处理经文引用,支持任意数量的-和+ - 正确生成节号列表:拆分每个片段,范围节展开为连续数字,零散节直接添加
- 按要求生成文件:以原经文引用为文件名,写入到指定的Obsidian vault目录
- 错误处理:添加异常捕获,避免单个错误导致整个脚本终止
- 编码统一:指定
utf-8编码,避免中文或特殊字符乱码
内容的提问来源于stack exchange,提问作者Quinton Powell
相关产品推荐
相关产品推荐

