【问题标题】:Extract value from a multiline pattern using PHP and preg_match使用 PHP 和 preg_match 从多行模式中提取值
【发布时间】:2012-07-05 22:29:56
【问题描述】:

我正在尝试使用 PHP 和 preg_match 从多行模式中提取一个值。 我在传递给 preg_match($regex, $string, $the_match) 的字符串中搜索的模式:

Latitude:</td>
        <td class="formCell">
        40-45-40.205 N
       </tr>

我知道如果它们都像这样在一行上:

Latitude:</td><td class="formCell">40-45-40.205 N</tr>

那么以下将是有效的,它会正确提取值:

/Latitude:<\/td><td class="formCell">(.*?)<\/tr>/

但是,由于我要查找的模式有多行,因此上述正则表达式不起作用。我正在通过 file_get_contents($url) 获取我传递给 preg_match() 的初始字符串,所以我在某种程度上受远程内容的支配。任何帮助将不胜感激!

【问题讨论】:

  • 完整答案:/Latitude:[\s]*[\s]*([\s\S]*?)[\s ]*/

标签: php preg-match multiline


【解决方案1】:

使用[\s\S] 而不是.

/Latitude:<\/td>[\s]*<td class="formCell">([\s\S]*?)<\/tr>/

. 是通配符,但不包括空格 - 包括换行符 - 字符。 [\s\S] 只是说“匹配所有空格和非空格字符”。

注意我还允许在&lt;/td&gt; 之后使用可选的空格字符。

(旁注:HTML 无效 - 在关闭表格单元格之前关闭表格行。)

【讨论】:

  • 赢家鸡肉晚餐!! (几乎)我不得不在 之后添加另一个“[\s]*”。如下所示:/Latitude:[\s]* [\s]*([\s\S]*?)/
  • 嗯...这应该不是必需的,因为那里的任何空格字符都会被接受空格字符的子组拾取。它对我有用。
  • 更新:我还必须在提取值的位置之后添加[\s]*/Latitude:&lt;\/td&gt;[\s]*&lt;td class="formCell"&gt;[\s]*([\s\S]*?)[\s]*&lt;\/tr&gt;/
  • 如果我在提取值之前和之后没有添加那些[\s]*,那么换行符会随着被提取的值传入。您可以在 Rubular 上快速测试它。
【解决方案2】:

没有简单的标志。一个简单的 hack 可能是:

Latitude:(.*?)<\/td>(.*?)<td class="formCell">(.*?)<\/tr>

然后将 dotall 标志添加到您的正则表达式以允许 '.'[dot] 也匹配换行符。 但它可以匹配更多。它是您自己的代码还是您从第三方网站翻录 html?因为也许你在不必要的时候使用了正则表达式!

【讨论】:

  • 我试过了,没用。 @Utkanos 在大多数情况下都是正确的。
【解决方案3】:

我认为诀窍是在任何 HTML 形式合法允许空白的地方“散布”[\s]*。你不需要特殊的标志或任何东西。

Latitude:[\s]*<\/td>[\s]*<td[\s]*class="formCell">[\s]*([\s\S]*?)[\s]*<\/tr>

请记住,html 对空格非常宽容。您需要评估您的输入并确定您可以接受的容忍度。

另一个需要注意的是,这些元素可能具有不同的属性或不同的引用样式...如果您也必须使用它,则需要使用更多的 .,然后使用“未就绪”标志(添加u 传递给 preg 函数时的模式之后);然后,一旦您意识到 > 可以合法地出现在属性内部,也许会进行一些花哨的反向引用;-)

【讨论】:

  • 在我最初的测试中,我使用了\s,没有方括号和星号。我使用Rubular 进行测试,在快速参考部分中,他们从未提到将\s 括在方括号中。其他所有寻求帮助的地方也从未提及多余的字符。
  • 我想它们并不是绝对必要的(它创建了一个字符“类”,但只有一个成员可能有点过分了)。星号是我建议的关键部分,而且位置丰富。
猜你喜欢
相关资源
最近更新 更多
热门标签