
本文详解如何使用 PHP 的 preg_match 正确解析含数字前缀(如“2 Chronicles”)或纯名称(如“Hebrews”)的圣经经文字符串,准确分离书卷名、章号和节数,并保持原始命名顺序。
本文详解如何使用 php 的 `preg_match` 正确解析含数字前缀(如“2 chronicles”)或纯名称(如“hebrews”)的圣经经文字符串,准确分离书卷名、章号和节数,并保持原始命名顺序。
在处理圣经经文文本(如 "2 Chronicles 10.16" 或 "Hebrews 11.6")时,常见误区是将数字前缀(如 2)误匹配为书卷名的一部分,或错误捕获空格/标点导致分组错位。核心挑战在于:书卷名可能以数字开头(如 1 Samuel, 3 John),也可能无数字(如 Acts, Psalms),且章与节之间统一使用英文句点 . 分隔(非冒号 :)。
以下是一个健壮、可扩展的正则方案:
<?php $verses = [
"Hebrews 11.6",
"2 Chronicles 10.16",
"Romans 13.13",
"2 Kings 5.10",
"3 John 1.5"
];
foreach ($verses as $verse) {
// 正则说明:
// (?:(\d+)\s+)? → 可选捕获前置数字(如"2"),后跟至少一个空白符
// (\w+) → 必选捕获书卷主名称(如"Chronicles"、"Kings"、"John")
// \s+ → 匹配书名与章号间的空白
// (\d+) → 捕获章号
// \. → 字面匹配句点(注意:需转义)
// (\d+) → 捕获节数
if (preg_match('/^(?:(\d+)\s+)?(\w+(?:\s+\w+)*)\s+(\d+)\.(\d+)$/', trim($verse), $matches)) {
$volume = $matches[1] ?? null; // 如存在,为"2"、"3"等
$book = $matches[2]; // 如"Chronicles"、"Kings"、"John";注意:此为纯名称,不含数字前缀
$chapter = $matches[3];
$verseNo = $matches[4];
// 构建符合语义的完整书卷名:数字前缀 + 书名(如"2 Chronicles")
$fullBook = $volume ? $volume . ' ' . $book : $book;
echo "Book {$fullBook} Chapter {$chapter} verse {$verseNo}\n";
} else {
echo "❌ Unmatched: '{$verse}'\n";
}
}
输出结果:
Book Hebrews Chapter 11 verse 6 Book 2 Chronicles Chapter 10 verse 16 Book Romans Chapter 13 verse 13 Book 2 Kings Chapter 5 verse 10 Book 3 John Chapter 1 verse 5
✅ 关键改进点:
- 使用 ^ 和 $ 锚定边界,避免部分匹配;
- (\w+(?:\s+\w+)*) 支持多词书名(如 "2 Chronicles" 中的 Chronicles 实际为单词,但该写法也为 "Song of Solomon" 等长书名预留扩展性);
- 显式区分 volume(数字前缀)与 book(核心名称),再拼接成语义完整的书卷名;
- 严格匹配 . 而非 :,贴合用户原始数据格式;
- trim() 预处理消除首尾空格,提升鲁棒性。
⚠️ 注意事项:
- 该正则假设书卷名仅含字母、空格及常见连字符(如 Song-of-Solomon 需额外调整 \w+ 为 [\w\-]+);
- 若需支持希腊文、希伯来文或带重音字符(如 Éphésiens),应将 \w+ 替换为 Unicode 感知模式,例如 [\p{L}\p{N}\s]+ 并添加 u 修饰符;
- 生产环境建议对 $matches 进行空值检查,避免未匹配时的索引错误。
通过此方案,您不仅能精准提取结构化数据,还能为后续构建经文索引、跨译本对照或 API 响应奠定坚实基础。











