You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP preg_match_all仅提取首个字段,其余匹配失败求助

从PDF转换文本中提取联系人字段的问题解决

问题描述

需要从PDF转换的文本中提取Navn(姓名)、Telefon(电话)、E-postadresse(邮箱)和Adresse(地址)字段的值,文本以空行分隔内容。但使用PHP的preg_match_all提取时,仅能获取首个Navn字段的值,其余字段匹配失败。

原始文本内容

Kontaktperson:

    Navn: Johan Wathne

    Telefon: 99566530

    99566530

    E-postadresse: johancqöhwheno

现有PHP代码

if (preg_match('/Kontaktperson:\s*(.*?)\n\n/ms', $fileContent, $matches)) {
    $kontaktpersonSection = trim($matches[1]);

    // Extract Tiltakshaver fields
    if (preg_match_all('/(Navn|Telefon|E-postadresse|Adresse):\s*([^\n]+)\s*(?:\n\n|$)/', $kontaktpersonSection, $kontaktMatches, PREG_SET_ORDER)) {
        $kontaktpersonInfo = "Kontaktperson\n";
        $currentkontakt = "";
        foreach ($kontaktMatches as $kontaktMatch) {
            if ($kontaktMatch[1] === "Navn") {
                $currentkontakt = "Navn";
                $kontaktValue = $kontaktMatch[2];
                $kontaktpersonInfo .= "$currentkontakt: $kontaktValue\n";
            } elseif ($kontaktMatch[1] === "Telefon") {
                $currentkontakt = "Telefon";
                $kontaktValue = explode("\n", $kontaktMatch[2])[0];
                $kontaktpersonInfo .= "$currentkontakt: $kontaktValue\n";
            } elseif ($kontaktMatch[1] === "E-postadresse") {
                $currentkontakt = "E-postadresse";
                $kontaktValue = $kontaktMatch[2];
                $kontaktpersonInfo .= "$currentkontakt: $kontaktValue\n";
            } elseif ($kontaktMatch[1] === "Adresse") {
                $currentkontakt = "Adresse";
                $kontaktValue = $kontaktMatch[2];
                $kontaktpersonInfo .= "$currentkontakt: $kontaktValue\n";
            }
        }
        $extractedInfo .= $kontaktpersonInfo;
    }
}

问题原因分析

  1. 第一个正则截断内容:/Kontaktperson:\s*(.*?)\n\n/ms中的.*?是惰性匹配,遇到第一个空行就停止捕获,导致$kontaktpersonSection只包含Navn部分,Telefon及之后的内容完全没进入处理流程。
  2. 第二个正则匹配范围不足:([^\n]+)仅匹配单行内容,即便内容完整传入,也无法处理Telefon这种跨两行的字段值,且匹配终止条件的逻辑也不够严谨。

修正方案与代码

核心修正点

  • 调整第一个正则的捕获范围,确保拿到完整的Kontaktperson区块,使用正向预查判断终止位置:/(?=\n\n\w+:|\z),即捕获到下一个空行加字段名或文本结尾为止。
  • 调整第二个正则,允许字段值跨多行,同样用正向预查匹配到下一个空行或结尾,确保完整捕获字段内容。

修正后的代码

if (preg_match('/Kontaktperson:\s*(.*?)(?=\n\n\w+:|\z)/ms', $fileContent, $matches)) {
    $kontaktpersonSection = trim($matches[1]);

    if (preg_match_all('/(Navn|Telefon|E-postadresse|Adresse):\s*(.*?)\s*(?=\n\n|\z)/ms', $kontaktpersonSection, $kontaktMatches, PREG_SET_ORDER)) {
        $kontaktpersonInfo = "Kontaktperson\n";
        foreach ($kontaktMatches as $kontaktMatch) {
            $field = $kontaktMatch[1];
            $value = trim($kontaktMatch[2]);
            
            // 针对Telefon字段的多行内容,这里示例取第一行,可根据需求调整(比如合并去重)
            if ($field === "Telefon") {
                $value = explode("\n", $value)[0];
            }
            
            $kontaktpersonInfo .= "$field: $value\n";
        }
        $extractedInfo .= $kontaktpersonInfo;
    }
}

代码说明

  • 第一个正则的正向预查(?=\n\n\w+:|\z)避免了提前截断,确保捕获Kontaktperson下的所有相关内容。
  • 第二个正则的.*?配合(?=\n\n|\z),能完整捕获每个字段的所有内容(包括换行),之后可根据业务需求处理多行值(如示例中的Telefon取第一行)。
  • 简化了循环逻辑,无需逐个判断字段类型,通用处理更简洁高效。

内容的提问来源于stack exchange,提问作者objelland

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:54:49