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

RegEx to match either words separated by dash or just a single word

所以,这个要求是匹配人的姓氏,每个姓氏之间用破折号分隔。

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

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

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

如果我使用像这样的示例,这将非常有效:

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

我尝试执行以下操作。

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

我在第一个匹配选项的允许字符中添加了一个\ 或space。我在没有 spaces.

的情况下为单个单词添加了一个或条件

虽然它适用于某些情况,但存在 2 个问题。

  1. 我不认为它是这种用例的最佳正则表达式。
  2. 我偶然发现了具有复杂姓氏的人的具体案例。

关于第2点,我指的是:

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

我不知道该如何处理。

此外,由于我添加了 space,它不再遵守单词之间破折号的要求。

我在想的可能是限制名字之间 space 的数量,比如在姓氏之间最多允许 2 或 3 个 space,这样的例子如下:

可以是有效匹配。

我不是 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',
      '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”,这将失败,因为它有一个 space 然后是一个撇号(两个连续的分隔符)。我不知道这是不是possible/real,我只是想澄清一下。

不需要环顾四周。