【问题标题】:RegEx to match either words separated by dash or just a single word正则表达式匹配由破折号分隔的单词或仅匹配单个单词
【发布时间】:2021-07-07 03:02:05
【问题描述】:

因此,对此的要求是匹配人的姓氏,每个姓氏之间用破折号分隔。

我为此使用的基本 RegEx 是这个:

(?=\S*[-])([a-zA-ZÑñÁáÉéÍíÓóÚúÄäËëÏïÖöÜüÀàÈèÌìÒòÙù'-]+)

基本上我将其限制为拉丁字母字符,包括一些重音字符。

如果我使用以下示例,这将非常有效:

  • 佩雷斯-冈萨雷斯
  • 多明格斯-迪亚兹
  • 格梅斯-马丁内斯

但我忘了考虑这个人只有一个姓氏的情况。

我尝试执行以下操作。

((?=\S*[-])([\ a-zA-ZÑñÁáÉéÍíÓóÚúÄäËëÏïÖöÜüÀàÈèÌìÒòÙù'-]+))|([A-Za-zÑñÁáÉéÍíÓóÚúÄäËëÏïÖöÜüÀàÈèÌìÒòÙù']+)

我在第一个匹配选项的允许字符中添加了\ 或空格。我为没有空格的单个单词添加了 or 条件。

虽然它适用于某些情况,但有两个问题。

  1. 对于这样的用例,我认为它不是最佳的 RegEx。
  2. 我偶然发现了与姓氏复杂的人有关的具体案例。

关于第 2 点,我指的是:

  • 约翰逊-德索萨

RegEx 匹配它,但它不再将破折号视为分隔符。

我不知道如何处理。

而且由于我添加了空格,它不再遵守单词之间的破折号的要求。

我的想法可能是限制名称之间的空格数,例如在姓氏之间最多允许 2 或 3 个空格,例如:

  • Pérez-De la Cruz - 这适用于我的 RegEx
  • Pérez De la Cruz-González - 这不是

可以是有效的匹配项。

我不是 RegEx 方面的专家,因此我们将不胜感激。

更新

我确实没有提到我需要能够将它与 JavaScript 一起使用。 PHP 也可能有用,但我正在做一些浏览器验证,并且模式需要兼容。

【问题讨论】:

  • 姓/名是字符串中唯一的吗?在纯文本中识别姓氏/姓氏可能非常困难。也许[[:alpha:]]+([- ']?) 更简单,似乎匹配所有示例但也很松散,例如asdfl 不是姓氏。
  • 是的,它专门用于姓氏。这就是为什么我不确定如何处理更复杂的问题。我不知道我是应该在 RegEx 中做一堆OR 条件还是只是简化所需的输入。
  • @user3783243 [[:alpha:]]+([- ']?) 建议很有趣,但它不适用于重音字符。
  • 使用u 标志,它应该扩展到重音。所以regex101.com/r/LsOqVr/1可以实现你的目标
  • @user3783243 我认为最后一个可以解决问题,但是当我在正则表达式的 JavaScript 中尝试它时,它会显示模式错误。

标签: javascript php regex regex-group regex-look-ahead


【解决方案1】:

从逻辑上讲,您应该匹配一个或多个字母,然后在允许另一个包含一个或多个字母的字符串之前允许您选择的分隔字符出现一次。

PHP 代码:(Demo)

$names = [
    'Pérez-González',
    'Domínguez-Díaz',
    'Güemez-Martínez',
    'Johnson-De Sosa',
    'Pérez-De la Cruz',
    'smith',
    'Pérez De la Cruz-González',
    'de Gal-O\'Connell',
    'Johnson--Johnson'
];

foreach ($names as $name) {
    echo "$name is " . (!preg_match("~^\pL+(?:[- ']\pL+)*$~u", $name) ? 'in' : '') . "valid\n";
}

Javascript 代码:(sn-p 可运行)

let names = [
      'Pérez-González',
      'Domínguez-Díaz',
      'Güemez-Martínez',
      'Johnson-De Sosa',
      'Pérez-De la Cruz',
      'smith',
      'Pérez De la Cruz-González',
      'de Gal-O\'Connell',
      'Johnson--Johnson'
    ],
    i,
    name;

for (i in names) {
    name = names[i];
    document.write("<div>" + name + " is " + (!name.match(/^\p{L}+(?:[- ']\p{L}+)*$/u) ? 'in' : '') + "valid</div>");
}

这将只允许在字母序列之间使用单个分隔符。如果您某人的名字是“Suzy 'Ng”,这将失败,因为它有一个空格,然后是一个撇号(两个连续的分隔符)。我不知道这是否可能/真实,我只是想澄清一下。

不需要环顾四周。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2017-07-08
  • 1970-01-01
  • 1970-01-01
  • 2021-10-20
  • 1970-01-01
相关资源
最近更新 更多