【问题标题】:Regular Expression to match all characters up to next match正则表达式匹配所有字符直到下一个匹配
【发布时间】:2012-05-09 07:20:47
【问题描述】:

我正在解析一个简单模式的多次重复文本。文本采用剧本的格式,如下所示:

SAMPSON
I mean, an we be in choler, we'll draw.

GREGORY
Ay, while you live, draw your neck out o' the collar.

我目前正在使用模式([A-Z0-9\s]+)\s*\:?\s*[\r\n](.+)[\r\n]{2},它可以正常工作(下面的解释),除非角色的语音中有换行符。发生这种情况时,角色的名字被成功捕获,但只捕获语音的第一行。

打开单行模式(在. 中包含换行符)只会创建一个巨大的匹配项。

如何告诉(.+) 在找到下一个字符名称并结束匹配时停止?
我正在单独迭代每个匹配项(JavaScript),因此该名称必须可用于下一个匹配项。

理想情况下,我可以匹配所有字符,直到整个模式重复。


模式解释:

第一组匹配字符的名称(允许大写字母、数字和空格),(尾随冒号和空格可选)。
第二组(角色的讲话)从新的一行开始并捕获任何字符(有问题的是,换行符和它们之后的字符除外)。
模式在空行之后结束(并重新开始)。

【问题讨论】:

  • 您需要明确定义如何确定下一个名称的开始位置,然后才能编写正则表达式来匹配它。它是一个单独的单词,后跟冒号吗?这会导致任何不正确的匹配吗?
  • @mellamokb 我忘了包含模式的最后一部分,它会寻找一个空行。匹配从角色的名字开始(所有大写在自己的一行),并在演讲后的空白行结束。
  • 我相信您的示例文本中缺少冒号,正则表达式无法使用它。
  • @TheronLuhn 冒号应该是可选的;如果它丢失,正则表达式应该仍然有效。换行符是重要的部分。
  • 无论它应该做什么,您的样本都不能与您的正则表达式一起使用,这对我们没有多大帮助。除了冒号,您的正则表达式最后似乎需要 2 个换行符,这也没有反映在示例中。

标签: javascript regex parsing


【解决方案1】:

考虑采取不同的方向。您真的想在包含名称的任何行上拆分更大的对话。您仍然可以使用正则表达式来执行此操作(将正则表达式替换为与“扬声器”行匹配的任何内容):

results = "Insert script here".split(/^([A-Z]+)$/)

在符合标准的实现中,您的示例文本最终会出现在一个数组中,如下所示:

results[0] = ""
results[1] = "SAMPSON"      
results[2] = "I mean, an we be in choler, we'll draw.            
"
results[3] = "GREGORY"      
results[4] = "Ay, while you live, draw your neck out o' the collar. "

需要注意的是,大多数浏览器在此处的标准上参差不齐。您可以使用库 XRegExp 来获得跨平台行为。

【讨论】:

  • 在我的用例中,将对话框分成单独的行没有意义。由于程序(和用户)作为一个整体与对话框交互,我只需将它们再次拼接在一起,这样它们就会有用。
【解决方案2】:

好的,我做了一些修改,发现了一些可行的方法。它不是超级优雅,但可以完成工作。

([A-Z0-9\s]+)\s*\:?\s*[\r\n]((.+[\r\n]?.*)+)[\r\n]{2}

我修改了最后一个捕获组以允许无限重复任意文本、新行和更多任意文本。由于不允许连续两个换行符,因此该模式在演讲后结束。

【讨论】:

  • 我只是想指出,我将您问题中的正则表达式和示例粘贴到a regex testing tool 然后简单地启用 dotall 模式(点匹配换行符)解决了您的问题。奇怪的是对你不起作用
【解决方案3】:

我终于设法让它只匹配你想要的,即
- 字符的名称,允许使用空格和冒号
- 以及可选的多行换行符,与人相关的文本

您需要使用此正则表达式执行findAll - 它区分大小写:

((?:[A-Z]{2,}\s*:?\s*)+)\s+((?![A-Z]{2,}\s*:?\s*).+?[.?!]\s*)+

解释:

  • ((?:[A-Z]{2,}\s*:?\s*)+) - 第一组捕获人的大写姓名 - 它将匹配 'GREGOR' 以及 'MANFRED THE GREATEST:'
  • \s+ - 至少一个空格字符
    然后至少重复一次:
  • (?![A-Z]{2,}\s*:?\s*) - 提前检查下一个文本是否不是大写字符名称
  • .+?[.?!]\s* - 匹配所有内容,直到找到一个以句子结尾的字符 [.?!] 和可选的空格

【讨论】:

    猜你喜欢
    • 2019-04-17
    • 2023-03-13
    • 2015-07-18
    • 1970-01-01
    • 2017-09-02
    • 1970-01-01
    • 1970-01-01
    • 2011-09-26
    • 2022-11-02
    相关资源
    最近更新 更多