【问题标题】:How to match every space preceded by at least 6 characters since the last matched space?自上次匹配空格以来,如何匹配前面至少有 6 个字符的每个空格?
【发布时间】:2020-09-01 23:54:22
【问题描述】:

我从最近删除的一个问题中复制了这个问题,我认为这个问题很有趣,但很难回答。

tl;博士:

如何匹配前面至少有 6 个字符且不包含任何匹配空格的空格?


我正在尝试编写这个正则表达式来匹配它们之间有 6 个或更多字符/不匹配空格的空格,以便我可以使用 .split() 将它们分成不同的行。

示例:

  • 凯亚·迪瓦恩·拉赫曼
  • 祖奈拉球场凯恩斯
  • 奥利维亚·拉莫斯·史密斯
  • 唐纳德·本·埃德·贾克斯

我目前拥有的:/(?<=.{6,})\s/g

这不能正常工作。例如,它匹配姓氏中的所有空格(拆分结果:['Donald', 'Ben', 'Ed', 'Jax'])。相反,我希望拆分结果为['Donald', 'Ben Ed', 'Jax']。你如何使它在第一个匹配之后(唐纳德之后的空格)开始从那个索引开始搜索?

【问题讨论】:

  • Lookbehind 是一种非消耗模式,因此您不能在此处使用它。 \K 不受支持,因此您需要一个匹配的正则表达式,而不是拆分正则表达式。请提供模式要求。
  • 从你说的这个也不应该被选中:Kayiya~here~Devine Rehman ?
  • 您将Kaiya(5 个字符)拼错为Kayiya(6 个字符)。在您的示例中,应该匹配第一个空格,是的。因为它前面至少有 6 个不包含匹配空格的字符。
  • 'Zunairah Field Cairns' 中,考虑到'Field' 是五个字符,而'Field' 之前的空格匹配,为什么'Field' 之后的空格匹配?对于'Oliwia Ramos Smith''Ramos' 之后的空格,同样的问题。
  • 我没有注意到那些也是不正确的匹配。但是当前的最佳答案可以正确处理它们(与它们不匹配)。

标签: javascript regex


【解决方案1】:

答案是(?<=(\S|(?<!\S{6,})\s){6,})\s

Test it here at Regex101

【讨论】:

  • 这与'Donald Ben Ed Jax''Ed''Jax' 之间的空格不匹配。
  • @GirkovArpa 为什么会这样? 'Ed' 只有 2 个字符长,您至少需要 6 个字符才能匹配一个空格。
  • 因为它匹配'Donald Ben Ed Jax' 中的第一个空格,所以'Ben Ed Jax' 没有匹配。 'Ben Ed' 有 6 个字符长,所以它后面的空格应该匹配。目标是将名称分成长度为 6 个字符的段,但仅限于空格处,而不是之前。
  • @GirkovArpa 新的和改进的。
  • 你能在链接的正则表达式测试器中演示你的正则表达式吗?您的后视在 regex101.com 上被标记为错误(这让我很吃惊)。我不知道 Javascript,但我读过它并不总是支持后视、固定或可变长度,即使现在有些浏览器也不接受 Javascript 后视。请澄清。
【解决方案2】:

简单的/(^\w+)\s(.+)\s(\w+)$/不是你真正需要的吗? https://regex101.com/r/phAKGH/1

【讨论】:

  • 我很抱歉,但我不得不收回您的最佳答案,因为它在以下字符串上失败:Orange Banana Apple Gooseberry Plum。它不会在任一空间破坏Banana Apple Gooseberry
  • 我只是觉得你需要简单的名字/中间名/姓氏。但是,如果您真的需要 6 个字符的逻辑,那么使用 /\w{6,}/ 之类的正则表达式并在字符串上循环就足够了?
  • 它也会在Kaiya 之后的空格处立即拆分,因为它只有 5 个字符长。
【解决方案3】:

我会做更多类似的事情:

function separateName(name){
  const a = name.split(/\s+/);
  if(a.length > 3){
    a[1] += ' '+a.splice(2, 1);
  }
  return a;
}
const testArray = ['Kaiya Devine Rahman', 'Zunairah Field Cairns', 'Oliwia Ramos Smith', 'Donald Ben Ed Jax'];
for(let n of testArray){
  console.log(separateName(n));
}

【讨论】:

  • 这是一种实用的解决方法,但在技术上并不能回答问题。
【解决方案4】:

我已采取以下方法来避免使用lookbehinds,因为我知道并非所有浏览器都支持它们。

如果您匹配以下正则表达式,则每次匹配后都会有一个感兴趣的空间。

/(?:^| ).{6}[^ \n]*(?= )/

Start your engine!

例如,如果字符串是:

"Now is the time for exceptional  Rubiests to be extra vigilent in the testing phases"

会有 8 个匹配项(注意'Rubiests' 之前有两个空格):

"Now is"
" the time"
" for exceptional"
"  Rubiests"
" to be extra
" vigilent"
" in the"
" testing"

每个匹配的第一个字符但第一个是匹配的空格;也就是说,该空格前面至少有 6 个字符,跟在最后一个匹配的空格或字符串的开头之后。

这 8 个匹配项在连接时构成字符串的第一部分。因此很容易计算每个匹配空间的索引。

【讨论】:

  • 我试过你的模式。 (这不是主要的,但没有选择最后一个单词或组)我的问题是你如何使用该正则表达式来分隔字符串而不留下空格。
  • 啊,我没注意到"...split()..."。我按照标题进行,我建议您将其更改为“如何在每个空格上拆分字符串,自上次匹配空格以来至少有 6 个字符?”。您仍然需要更正问题中的“Field”和“Ramos”。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多