【问题标题】:Is there a way to move/reset the search pointer in preg_match_all()?有没有办法在 preg_match_all() 中移动/重置搜索指针?
【发布时间】:2011-06-30 19:28:51
【问题描述】:

举个例子,

preg_match_all("/(^|-)[a-z]+(-|$)/i", "foo-bar-moo", $matches);

这(正确)返回以下匹配项,

foo-
-moo

但是,我需要生成以下匹配输出,

foo-
-bar-
-moo

真的有办法做到这一点吗?例如,在匹配后将搜索指针移回一个字符?

我唯一的另一个想法是将其放入 while() 循环中,删除每个循环上的匹配项,直到找到所有匹配项。

谢谢。

编辑:我试图简化我的问题以使问题更清晰,但这样做我似乎歪曲了我的问题实际上是什么。道歉。

基本上,我需要一种方法来匹配字符串中的单词,其中紧接其前的字符或紧随其后的字符是某个字符,但同时不捕获匹配中的这些前导和尾随字符。

我的印象是你不能这样做,所以我决定捕获前导/尾随字符并自己删除它们。这导致了我上面的问题。

正如 Tim Pietzcker 所指出的,我真正需要的是 lookarounds

所以对于我上面的例子,解决方法如下,

preg_match_all('/(?<=^|-)[a-z]+(?=-|$)/', "foo-bar-moo", $result);

它会输出,

foo
bar
moo

再次感谢您的回答和帮助。

【问题讨论】:

  • 你能把连字符设为可选吗(我认为这是语法)? (^|-)?[a-z]+(-|$)?
  • 不行,如果匹配,我需要获取-'s。

标签: php regex


【解决方案1】:

使用环视并将捕获组放在环视表达式中。这允许您在单个 preg_match_all() 调用中执行此操作,并且仍然捕获 -es(如果存在):

preg_match_all('/(?<=(^|-))([a-z]+)(?=(-|$))/', $subject, $result, PREG_SET_ORDER);
for ($match = 0; $match < count($result); $match++) {
    echo $result[$match][1] . $result[$match][2] . $result[$match][3];
}

【讨论】:

  • 您先生是个学者和绅士。我的问题中的示例与我的实际问题相比非常抽象(抱歉),而环视表达式正是我解决问题所需要的。谢谢。
【解决方案2】:

我认为您必须在preg_match 中使用offset 参数。从 0 开始,得到-*[a-z]-* 的第一个匹配项。获取matchOffset + matchLength - #dashesAtEnd 并将其用作下一个preg_match 调用的偏移量。

【讨论】:

  • 这是一个选项。但是,我有大量内容正在测试中,并且生成了一个 long 正则表达式。理想情况下,我很想将一些东西传递给preg_match_all(),所以我只需要运行一次即可获得性能。
  • @Stephen,我认为 preg_match_all 必须做几乎相同的事情,除了不减少当前偏移量。您确定这是性能问题吗?
  • @agent-j:我会做一些基准测试,看看多次运行它是否真的会产生影响。为这个建议喝彩。希望我可以使用它。
  • @agent-j:因此,对于 preg_match_all() 是最快的,甚至减少了 80% 的时间。但是对于更长的字符串,多次运行preg_match() 会更快。例如,我跑了preg_match() 5 次。因为无论如何我们都在谈论毫秒,所以我很高兴与preg_match() 一起生活。再次欢呼。
  • @斯蒂芬。凉爽的!感谢您报告。
【解决方案3】:

怎么样

preg_match_all("/(^|-)([a-z])+(-|$)/i", "foo-bar-moo", $matches);

你会得到 [foo,bar,moo]。

【讨论】:

  • 除非我遗漏了什么,否则这与我的问题中的正则表达式没有什么不同并给出相同的结果?
【解决方案4】:

认为你需要:

Array
(
    [0] => foo-
    [1] => -bar-
    [2] => -moo
)

但正如我从您更新的问题中看到的那样,这也应该有效:

preg_match_all("/(?-)[a-z]+(?-)/i", "foo-bar-moo", $matches);

echo $matches[0];

Array
(
    [0] => foo
    [1] => bar
    [2] => moo
)

【讨论】:

    猜你喜欢
    • 2013-02-04
    • 2017-04-02
    • 1970-01-01
    • 2019-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-13
    • 1970-01-01
    相关资源
    最近更新 更多