正则表达式匹配以破折号分隔的单词或仅匹配一个单词

问题描述

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

我为此使用的基本正则表达式是:

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

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

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

  • 佩雷斯-冈萨雷斯
  • 多明格斯-迪亚兹
  • Güemez-Martínez

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

我尝试执行以下操作。

((?=\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 也可能很有用,但我正在做一些浏览器验证并且模式需要兼容。

解决方法

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

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 代码:(代码段可运行)

let names = [
      'Pérez-González','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”,这将失败,因为它有一个空格,然后是一个撇号(两个连续的分隔符)。我不知道这是否可能/真实,我只是想澄清一下。

不需要环顾。