正则表达式和撇号

My answer is almost like this one: Pregmatch for at least 3 letters and for minus and apostrophe

So, I need too a regex for a name validation. But my rules are a little different:

  • must start with a letter;
  • no numbers and no alphanumeric;
  • must have at least three letters (also not only consecutive... anywere in the name) and max 20;
  • can accept only one apostrophe (') or no one else -these are the only special characters that can be used ...(not mandatory and anywere in the name). it doesnt matters where you put the apostrophe

    for ex:

    d'amico => must be accepted;
    d'amico' => no d''amico => no 'oneil => no dell'amore => yes damico => yes king kong => yes io => no io9 => no
    8888 => no aaa+++? => no

Until now I have this code:

<?php
...
    // Array errori
    $error = array(); // o $error = []; se hai una versione di php recente

    // Controllo il Nome Utente
    if(trim($nome) == ''){
        $error[] = 'Campo nome non compilato'; }

    if (ctype_alnum($nome)) 
        {$error[] = 'Se vuoi modificare il campo nome, assicurati che lo 
             stesso non contenga numeri al suo interno!'; }  

    if(strlen($nome) < 3 || strlen($nome) > 20){
        $error[] = 'Il campo nome deve contenere minimo 3 caratteri e massimo 20 caratteri'; }

    if (!preg_match("/^([A-Za-z|àèéìòù][A-Za-z'-]*?){3,}$/", $nome)) {
        $error[] = 'Il campo nome contiene caratteri non ammessi'; } 

...

?>

<html>...

<?php 
      if(!empty($error)){
         echo  '<center>';
         echo implode('<br/>', $error);
        echo  '</center>';
      }
   ?>

...
</html>

How can I combine everything into one string? Thank you in advance!

Using a negative lookahead you can assert that the string doesn't start with a ', whitespace, or contain 2 (or more) single quotes. Then you can just test that the string is between 3 and 20 characters long with your allowed character list.

(?!(.*?'.*?'|^[' ]))^[A-Za-z|àèéìòù ']{3,20}$

Regex Demo: https://regex101.com/r/QANVBo/1

PHP Demo: https://eval.in/659769

PHP Usage:

$array = array("d'amico", "dell'amore", "damico", "king kong", "io", "io9", "8888", "aaa+++?", "d'amico'", "d''amico", "'oneil");
foreach ($array as $term ) {
     if(preg_match("/(?!(.*?'.*?'|^[' ]))^[A-Za-z|àèéìòù ']{3,20}$/", $term)) {
          echo 'Matches:';
     } else {
          echo 'No Match:';
     }
     echo $term . "
";
}