【问题标题】:How Do I Split a String by Periods but Ignore Salutations?如何按句点拆分字符串但忽略称呼?
【发布时间】:2012-12-22 15:12:27
【问题描述】:

我非常清楚这是一个不平凡的问题。

我目前有这个:

(.*?)(!,"\s|!,"$|\.\s|\.$|\!"?\s+?|\!"?$|\?"?\s+?|\?"?$|\."\s+?|\."$|…"\s+?|…"?$)

匹配各种行尾位和拆分句子/段落。它做得很好。

但是,给定句子:

Hello, Dr. Smith. How are you?

我想把它分成:

  1. Hello, Dr. Smith.
  2. How are you?

我现有的解决方案会产生类似的结果:

  1. Hello, Dr.
  2. Smith.
  3. How are you?

有一整套称呼(否定)匹配:

Dr.|Prof.|Mr.|Mrs.|Ms.

任何想法如何做到这一点?

【问题讨论】:

  • 你想要一个消极的后视regular-expressions.info/lookaround.html
  • 你的问题是什么?...你想要什么..用例子说明你的问题
  • @lc - 没错,但正确的语法实际上应该是“你好,医生。微笑。”或者,“你好,医生。微笑。” Dr. 应该只出现在一个人名字的专有名词之前,在这种情况下我可以接受不匹配的情况。
  • 好吧,例如this 就可以完成这项工作-但这是否适合您取决于您​​想要什么。该示例在句点后面的空白字符上拆分 - 这意味着必须至少有一个空白字符,否则它将不起作用。不幸的是,有必要在后视中包含每个项目之后的句点 - 为了避免这种情况,您需要在后视中放置一个组,这是无法做到的,因为列表项的宽度不是固定的。
  • ...或者您可以在后向拆分(如this),但如果您这样做,则空白字符将留在下一项的开头。

标签: php regex text-parsing preg-split


【解决方案1】:

我怀疑你正在盯着一个兔子洞。如果您选择走这条路,请为一些无法预料的挑战做好准备。

至于您最直接的要求,列出您的非拆分匹配项,然后使用(*SKIP)(*FAIL) 丢弃这些匹配项并继续匹配应该触发拆分点的字符串。

\K 将重置全字符串匹配。这意味着之前匹配的字符不会在爆炸中被删除。制作这些元素时只会使用空白字符。

代码:(Demo)

$text = <<<TEXT
Dr. Di MacKusa is a doctor.  Do you know her?!?  She live on 1 Doctor Dr. Doctorsville in the U.S.A. Mr. MacKusa married Dr. Di.
TEXT;

var_export(
    preg_split(
        '~(?:Ms|Dr|Mrs?|Prof)\.(*SKIP)(*FAIL)|[?!.]+\K\s+~',
        $text,
        0,
        PREG_SPLIT_NO_EMPTY
    )
);

输出:

array (
  0 => 'Dr. Di MacKusa is a doctor.',
  1 => 'Do you know her?!?',
  2 => 'She live on 1 Doctor Dr. Doctorsville in the U.S.A.',
  3 => 'Mr. MacKusa married Dr. Di.',
)

通过更全面的示例文本,我可以改进我的模式。我的模式是一个相当简单的解决方案,我们尚未设计为正确处理引用的文本。

【讨论】:

    猜你喜欢
    • 2022-11-22
    • 2022-01-07
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    • 2011-02-16
    • 1970-01-01
    相关资源
    最近更新 更多