Espressione regolare per nome e cognome


124

Ai fini della convalida del sito Web, ho bisogno della convalida del nome e del cognome.

Per il nome, deve contenere solo lettere, può essere composto da più parole con spazi e ha un minimo di tre caratteri, ma un massimo di 30 caratteri superiori. Una stringa vuota non dovrebbe essere convalidata (ad esempio Jason , jason , jason smith , jason smith , JASON , Jason smith , jason Smith e jason SMITH ).

Per il cognome, dovrebbe essere una sola parola, solo lettere, con almeno tre caratteri, ma al massimo 30 caratteri. Le stringhe vuote non dovrebbero essere convalidate (ad esempio lazslo , Lazslo e LAZSLO ).


10
E i nomi come "Jo"?
a'r

6
solo un'osservazione: i trattini sono comuni nei cognomi ... forse ci sono anche
cognomi

2
Nota: un validatore di espressioni regolari ignorerà gli input vuoti: questo potrebbe o non potrebbe essere quello che vuoi.
Hans Ke st ing

4
Se possibile, a meno che tu non abbia una ragione sorprendentemente convincente per richiedere un nome e un cognome, fornisci un solo campo "Nome". kalzumeus.com/2010/06/17/…
Chris

Risposte:


195

Non dimenticare nomi come:

  • Mathias d'Arras
  • Martin Luther King, Jr.
  • Hector Sausage-Hausen

Questo dovrebbe fare il trucco per la maggior parte delle cose:

/^[a-z ,.'-]+$/i

OPPURE Supporta nomi internazionali con unicode super dolce:

/^[a-zA-ZàáâäãåąčćęèéêëėįìíîïłńòóôöõøùúûüųūÿýżźñçčšžÀÁÂÄÃÅĄĆČĖĘÈÉÊËÌÍÎÏĮŁŃÒÓÔÖÕØÙÚÛÜŲŪŸÝŻŹÑßÇŒÆČŠŽ∂ð ,.'-]+$/u


4
Vorrei sfuggire ai caratteri speciali in queste espressioni regolari, in particolare .(punto decimale / punto / punto) poiché è il carattere jolly regexp =)
Joel Purra

30
Non è possibile convalidare tutti i possibili caratteri nazionali. Ad esempio őŐűŰ, mancano caratteri ungheresi , anche caratteri polacchi łŁ, per non parlare di un certo numero di caratteri lituani e lettoni. Piuttosto prova a trovare una libreria che trasformi i personaggi esotici nella corretta versione senza accenti, quindi scrivi la /^[a-z ,.'-]+$/iregexp.
gaborsch

69
Quindi 陳大文non è un nome valido qui?
Alvin Wong

16
Per Unicode, usa /^[\p{L}'][ \p{L}'-]*[\p{L}]$/u, comunque abbastanza indulgente.
Frederik Krautwald

4
AZ non ha bisogno di essere incluso nell'esempio originale perché il modificatore i dopo l'espressione significa ignorare le maiuscole.
mhanney

73

Fai false supposizioni sul formato del nome e del cognome. Probabilmente è meglio non convalidare affatto il nome, a parte controllare che sia vuoto.


avrebbe dovuto essere un commento.
Demenziale

32

Dopo aver esaminato tutte queste risposte, ho trovato un modo per creare una piccola regex che supporta la maggior parte delle lingue e consente solo i caratteri delle parole. Supporta anche alcuni caratteri speciali come trattini, spazi e apostrofi. Ho provato in Python e supporta i caratteri seguenti:

^[\w'\-,.][^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]]{2,}$

Caratteri supportati:

abcdefghijklmnopqrstwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
áéíóúäëïöüÄ'
陳大文
łŁőŐűŰZàáâäãåąčćęèéêëėįìíîïłńòóôöõøùúûüųū
ÿýżźñçčšžÀÁÂÄÃÅĄĆČĖĘÈÉÊËÌÍÎÏĮŁ
ŃÒÓÔÖÕØÙÚÛÜŲŪŸÝŻŹÑßÇŒÆČŠŽ.-
ñÑâê都道府県Федерации
আবাসযোগ্য জমির걸쳐 있는

2
Di tutte le risposte, questa ha funzionato a meraviglia usando ng 4.
Deniss M.

1
La tua regex non riesce su una stringa di 2 caratteri. Penso che questo abbia risolto il problema^[\w'\-,.]*[^_!¡?÷?¿\/\\+=@#$%ˆ&*(){}|~<>;:[\]]*$
TKA

I caratteri nazionali sono supportati ma non in prima posizione. ^[^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]]{2,}$
Modificherei l'

18

Ho creato una regex personalizzata per gestire i nomi:

Ho provato questi tipi di nomi e ho trovato che funzionano perfettamente

  1. John Smith
  2. John D'Largy
  3. John Doe-Smith
  4. John Doe Smith
  5. Hector Sausage-Hausen
  6. Mathias d'Arras
  7. Martin Luther King
  8. Ai Wong
  9. Chao Chang
  10. Alzbeta Bara

La mia RegEx ha questo aspetto:

^([a-zA-Z]{2,}\s[a-zA-Z]{1,}'?-?[a-zA-Z]{2,}\s?([a-zA-Z]{1,})?)

Modello MVC4:

[RegularExpression("^([a-zA-Z]{2,}\\s[a-zA-Z]{1,}'?-?[a-zA-Z]{2,}\\s?([a-zA-Z]{1,})?)", ErrorMessage = "Valid Charactors include (A-Z) (a-z) (' space -)") ]

Si prega di notare il doppio \\per i caratteri di escape

Per quelli di voi che non conoscono RegEx ho pensato di includere una spiegazione.

^               // start of line
[a-zA-Z]{2,}    // will except a name with at least two characters
\s              // will look for white space between name and surname
[a-zA-Z]{1,}    // needs at least 1 Character
\'?-?           // possibility of **'** or **-** for double barreled and hyphenated surnames
[a-zA-Z]{2,}    // will except a name with at least two characters
\s?             // possibility of another whitespace
([a-zA-Z]{1,})? // possibility of a second surname

Ho uno unit test che verifica diversi nomi, quindi diverse cose che non sono nomi. L'elenco dei non nomi ha "test token" come prima voce. Questo corrisponde a quello.
Rob il

È quasi quello che stavo cercando. Immagino (forse a torto) che tu sia un ragazzo francese. E un caso non è handle che puoi incontrare in francese: nomi composti, come Jean-Pierre, Marie-Charlotte, ecc ... Sono nuovo a reg exp ma immagino un -? come hai fatto per il cognome, tra le prime 2 parole, potrebbe fare il lavoro.
Linpter

Ciao Linpter, non francese, tuttavia ho un nome francese. Sì. Non l'ho testato, tuttavia dovresti essere in grado di aggiungere - nel primo [] quindi cambia: ^ ([a-zA-Z] {2,} \ s [a-zA-z] {1,} ' ? -? [a-zA-Z] {2,} \ s? ([a-zA-Z] {1,})?) TO: ^ ([a-zA-Z -] {2,} \ s [a-zA-z] {1,} '? -? [a-zA-Z] {2,} \ s? ([a-zA-Z] {1,})?)
Francois Muller

16

Ho cercato, cercato, giocato e giocato con esso e sebbene non sia perfetto può aiutare gli altri a tentare di convalidare il nome e il cognome forniti come una variabile.

Nel mio caso, quella variabile è $ name.

Ho usato il seguente codice per il mio PHP:

    if (preg_match('/\b([A-Z]{1}[a-z]{1,30}[- ]{0,1}|[A-Z]{1}[- \']{1}[A-Z]{0,1}  
    [a-z]{1,30}[- ]{0,1}|[a-z]{1,2}[ -\']{1}[A-Z]{1}[a-z]{1,30}){2,5}/', $name)  
    # there is no space line break between in the above "if statement", any that   
    # you notice or perceive are only there for formatting purposes.  
    # 
    # pass - successful match - do something
    } else {
    # fail - unsuccessful match - do something

Sto imparando RegEx da solo, ma ho la spiegazione del codice fornita dall'amico RegEx.
Ecco qui:

Asserisci la posizione al confine di una parola «\ b»

Trova la corrispondenza con l'espressione regolare di seguito e acquisisci la sua corrispondenza nel backreference numero 1
«([AZ] {1} [az] {1,30} [-] {0,1} | [AZ] {1} [- \ '] { 1} [AZ] {0,1} [az] {1,30} [-] {0,1} | [az] {1,2} [- \ '] {1} [AZ] {1} [ az] {1,30}) {2,5} »

Da 2 a 5 volte, quante più volte possibile, restituendo se necessario (avido) «{2,5}»

* HO BISOGNO DI AIUTO QUI PER COMPRENDERE LE RAMIFICHE DI QUESTA NOTA *

Nota: ho ripetuto il gruppo di acquisizione stesso. Il gruppo acquisirà solo l'ultima iterazione. Metti un gruppo di acquisizione attorno al gruppo ripetuto per acquisire tutte le iterazioni. «{2,5}»

Trova la corrispondenza con l'espressione regolare sotto (tentando la successiva alternativa solo se questa fallisce) «[AZ] {1} [az] {1,30} [-] {0,1}»

Trova un singolo carattere nell'intervallo tra "A" e "Z" «[AZ] {1}»

Esattamente 1 volta «{1}»

Trova un singolo carattere nell'intervallo tra "a" e "z" «[az] {1,30}»

Da una a 30 volte, quante più volte possibile, restituendo se necessario (avido) «{1,30}»

Trova la corrispondenza di un singolo carattere presente nell'elenco "-" «[-] {0,1}»

Da zero a una volta, quante più volte possibile, restituendo se necessario (avido) «{0,1}»

Oppure trova l'espressione regolare numero 2 di seguito (tentando l'alternativa successiva solo se questa fallisce) «[AZ] {1} [- \ '] {1} [AZ] {0,1} [az] {1,30} [ -] {0,1} »

Trova un singolo carattere nell'intervallo tra "A" e "Z" «[AZ] {1}»

Esattamente 1 volta «{1}»

Trova un singolo carattere presente nell'elenco sotto «[- \ '] {1}»

Esattamente 1 volta «{1}»

Uno dei caratteri "-" «-» A 'carattere «\'»

Trova un singolo carattere nell'intervallo tra "A" e "Z" «[AZ] {0,1}»

Da zero a una volta, quante più volte possibile, restituendo se necessario (avido) «{0,1}»

Trova un singolo carattere nell'intervallo tra "a" e "z" «[az] {1,30}»

Da una a 30 volte, quante più volte possibile, restituendo se necessario (avido) «{1,30}»

Trova la corrispondenza di un singolo carattere presente nell'elenco "-" «[-] {0,1}»

Da zero a una volta, quante più volte possibile, restituendo se necessario (avido) «{0,1}»

Oppure trova l'espressione regolare numero 3 di seguito (l'intero gruppo fallisce se questa non riesce a trovare la corrispondenza) «[az] {1,2} [- \ '] {1} [AZ] {1} [az] {1,30} »

Trova un singolo carattere nell'intervallo tra "a" e "z" «[az] {1,2}»

Da una a 2 volte, quante più volte possibile, restituendo se necessario (avido) «{1,2}»

Trova un singolo carattere nell'intervallo tra "" e "'" «[- \'] {1}»

Esattamente 1 volta «{1}»

Trova un singolo carattere nell'intervallo tra "A" e "Z" «[AZ] {1}»

Esattamente 1 volta «{1}»

Trova un singolo carattere nell'intervallo tra "a" e "z" «[az] {1,30}»

Da una a 30 volte, quante più volte possibile, restituendo se necessario (avido) «{1,30}»

So che questa convalida presume totalmente che ogni persona che compila il modulo abbia un nome occidentale e questo potrebbe eliminare la stragrande maggioranza delle persone nel mondo. Tuttavia, credo che questo sia un passo nella giusta direzione. Forse questa espressione regolare è troppo semplice perché i guru possano affrontarla in modo semplicistico o forse c'è qualche altro motivo per cui non sono riuscito a trovare il codice sopra nelle mie ricerche. Ho passato troppo tempo a cercare di capire questo pezzo, probabilmente noterai quanto sia annebbiata la mia mente su tutto questo se guardi i nomi dei miei test di seguito.

Ho testato il codice sui seguenti nomi ei risultati sono tra parentesi a destra di ogni nome.

  1. STEVE SMITH (fallire)
  2. Stev3 Smith (fallire)
  3. STeve Smith (fallire)
  4. Steve SMith (fallire)
  5. Steve Sm1th (passato allo Steve Sm)
  6. d'Are a Beaware (passato sull'Are a Beaware)
  7. Jo Blow (superato)
  8. Hyoung Kyoung Wu (superato)
  9. Mike O'Neal (superato)
  10. Steve Johnson-Smith (superato)
  11. Jozef-Schmozev Hiemdel (superato)
  12. O Henry Smith (superato)
  13. Mathais d'Arras (superato)
  14. Martin Luther King Jr (superato)
  15. Downtown-James Brown (superato)
  16. Darren McCarty (superato)
  17. George De FunkMaster (superato)
  18. Kurtis B-Ball Basketball (superato)
  19. Ahmad el Jeffe (superato)

Se hai nomi di base, devono esserci più di uno fino a cinque affinché il codice sopra funzioni, che sono simili a quelli che ho usato durante il test, questo codice potrebbe essere per te.

In caso di miglioramenti, fatemelo sapere. Sono solo nelle prime fasi (i primi mesi per capire RegEx.

Grazie e buona fortuna, Steve


1
Cose come "Il quarto" o "IV" funzionerebbero con questo?
Majidarif

11

Il nome sarebbe

"([a-zA-Z]{3,30}\s*)+"

Se hai bisogno che l'intera parte del nome sia più corta di 30 lettere, devi controllarla separatamente, penso. L'espressione ".{3,30}"dovrebbe farlo.

I requisiti del tuo cognome si tradurranno in

"[a-zA-Z]{3,30}"

ma dovresti controllare questi. Ci sono molti cognomi che contengono spazi.


Questo controlla gli spazi tra?
Y_Y

2
E O'Connor ? Anche l'apostrofo deve essere incluso.
astronauta

1
Piuttosto incompleto. Il nome potrebbe essere "Jean-Claude" con trattino. Il cognome potrebbe essere "D'arc" con citazione. E se il nome fosse "François"?
bart

1
Che mi dici di "Al"? Nome valido. Solo due lettere. E i nomi cinesi, russi, hindi? E i nomi europei?
Christian Hujer

questo non funzionerebbe per molti nomi non inglesi o (non latini?)
oldboy

7

Come ha detto maček:

Non dimenticare nomi come:

Mathias d'Arras

Martin Luther King, Jr.

Hector Sausage-Hausen

e per rimuovere casi come:

..Mathias

Martin King, Jr.-

Questo coprirà più casi:

^([a-z]+[,.]?[ ]?|[a-z]+['-]?)+$

Se voglio limitare la lunghezza dei miei caratteri, quale potrebbe essere il codice per questo?
G.Abhisek

1
Sì, Martin Luther King Jr. ritorna in coppia, e così fa il re Enrico l'ottavo.
Steve Kinzey

7

Sto lavorando all'app che convalida i passaporti internazionali (ICAO). Supportiamo solo caratteri inglesi. Mentre la maggior parte dei caratteri nazionali stranieri può essere rappresentata da un carattere dell'alfabeto latino, ad esempio è con e, ci sono diversi caratteri nazionali che richiedono una lettera in più per rappresentarli, come la dieresi tedesca che richiede l'aggiunta di una 'e' alla lettera ad es. ä di ae.

Questo è il JavaScript Regex per il nome e il cognome che utilizziamo:

/^[a-zA-Z '.-]*$/

Il numero massimo di caratteri sul passaporto internazionale è fino a 31 . Usiamo maxlength = "31" per migliorare i messaggi di errore della parola invece di includerlo nella regex.

Ecco uno snippet del nostro codice in AngularJS 1.6 con form e gestione degli errori:

class PassportController {
  constructor() {
    this.details = {};
    // English letters, spaces and the following symbols ' - . are allowed
    // Max length determined by ng-maxlength for better error messaging
    this.nameRegex = /^[a-zA-Z '.-]*$/;
  }
}

angular.module('akyc', ['ngMessages'])
  .controller('PassportController', PassportController);
 
.has-error p[ng-message] {
  color: #bc111e;
}

.tip {
  color: #535f67;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.6/angular.min.js"></script>
<script src="https://code.angularjs.org/1.6.6/angular-messages.min.js"></script>

<main ng-app="akyc" ng-controller="PassportController as $ctrl">
  <form name="$ctrl.form">

    <div name="lastName" ng-class="{ 'has-error': $ctrl.form.lastName.$invalid} ">
        <label for="pp-last-name">Surname</label>
        <div class="tip">Exactly as it appears on your passport</div>
        <div ng-messages="$ctrl.form.lastName.$error" ng-if="$ctrl.form.$submitted" id="last-name-error">
          <p ng-message="required">Please enter your last name</p>
          <p ng-message="maxlength">This field can be at most 31 characters long</p>
          <p ng-message="pattern">Only English letters, spaces and the following symbols ' - . are allowed</p>
        </div>
        
        <input type="text" id="pp-last-name" ng-model="$ctrl.details.lastName" name="lastName"
               class="form-control" required ng-pattern="$ctrl.nameRegex" ng-maxlength="31" aria-describedby="last-name-error" />
      </div>

      <button type="submit" class="btn btn-primary">Test</button>

  </form>
</main>


@danieltakeshi, non hai usato il mio Regex. Usa questo: / ^ [a-zA-Z '.-] * $ /
Alexander Burakevych

5

Io uso:

/^(?:[\u00c0-\u01ffa-zA-Z'-]){2,}(?:\s[\u00c0-\u01ffa-zA-Z'-]{2,})+$/i

E prova la lunghezza massima usando altri mezzi


5

Questa regex funziona per me (stava usando in Angular 8):

([a-zA-Z',.-]+( [a-zA-Z',.-]+)*){2,30}

inserisci qui la descrizione dell'immagine

Non sarà valido se c'è: -

  1. Qualsiasi spazio bianco all'inizio o alla fine del nome
  2. Sono presenti simboli ad es. @
  3. Meno di 2 o più di 30

Esempio di nome non valido (spazio vuoto)

inserisci qui la descrizione dell'immagine

Esempio di nome valido:

inserisci qui la descrizione dell'immagine


6
Che ne dici di "Björk Guðmundsdóttir"?
Mariusz Jamro

4

Per semplicità, puoi usare:

(.*)\s(.*)

La cosa che mi piace di questo è che il cognome è sempre dopo il nome, quindi se hai intenzione di inserire questi gruppi corrispondenti in un database e il nome è John M. Smith, il primo gruppo sarà John M. e il secondo gruppo sarà Smith.


2
^\p{L}{2,}$

^ afferma la posizione all'inizio di una riga.

\ p {L} corrisponde a qualsiasi tipo di lettera di qualsiasi lingua

{2,} Quantificatore - Corrisponde da 2 a un numero illimitato di volte, il maggior numero di volte possibile, restituendo se necessario (avido)

$ afferma la posizione alla fine di una riga

Quindi dovrebbe essere un nome in qualsiasi lingua contenente almeno 2 lettere (o simboli) senza numeri o altri caratteri.


tieni presente che alcuni caratteri come "e - sono validi nei nomi.
Mathijs Segers

1

Quindi, con il cliente creiamo questa pazza regex:

(^$)|(^([^\-!#\$%&\(\)\*,\./:;\?@\[\\\]_\{\|\}¨ˇ“”€\+<=>§°\d\s¤®™©]| )+$)

1

Per nome e cognome ci sono solo 2 cose che dovresti cercare:

  1. Lunghezza
  2. Soddisfare

Ecco la mia espressione regolare:

var regex = /^[A-Za-z-,”{3,20}?=.*\d)/

1. Lunghezza

Qui il {3,20} vincola la lunghezza della stringa tra 3 e 20 caratteri.

2. Contenuto

Le informazioni tra le parentesi quadre [A-Za-z] ammettono caratteri maiuscoli e minuscoli. Sono consentiti anche tutti i simboli successivi (- ,.).


1

Questo è quello che uso.

Questa regex accetta solo nomi con caratteri minimi, da A-Z a-z ,space and -.

Esempio di nomi:

Ionut Ionete, Ionut-Ionete Cantemir, Ionete Ionut-Cantemirm Ionut-Cantemir Ionete-Second

Il limite del carattere del nome è 3. Se vuoi cambiarlo, modifica {3,} in {6,}

([a-zA-Z\-]+){3,}\s+([a-zA-Z\-]+){3,}

2
Che mi dici di ä å ö Ä Å Ö ecc? Molto comune nei nomi svedesi. Anche il cognome O'Conner fallirà e anche i nomi a doppia canna daranno problemi. Questo sarà molto frustrante per le persone che hanno nomi così validi.
Wilt

E l'apostrofo in nomi come O'Connor?
Fogmeister

la mia espressione restituisce Michael Jordan O'Reilly Jr. come nome valido
Steve Kinzey

0

La seguente espressione funzionerà su qualsiasi lingua supportata da UTF-16 e garantirà che ci siano almeno due componenti per il nome (cioè primo + ultimo), ma consentirà anche un numero qualsiasi di secondi nomi.

/^(\S+ )+\S+$/u

Al momento della stesura di questo articolo sembra che nessuna delle altre risposte soddisfi tutti questi criteri. Anche ^\p{L}{2,}$, che è il più vicino, non è all'altezza perché corrisponderà anche a caratteri "invisibili", come U+FEFF(Zero Width No-Break Space).


non passa javascript per regexr.com 1) avvertendo che la funzione Unicode potrebbe non essere supportata in tutti i browser. 2) inoltre consente i numeri nella regex. esempio: michael dimmittsasd2123123
Michael Dimmitt

0

Prova queste soluzioni, per la massima compatibilità, come ho già postato qui :

JavaScript:

var nm_re = /^(?:((([^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]'’,\-.\s])){1,}(['’,\-\.]){0,1}){2,}(([^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]'’,\-. ]))*(([ ]+){0,1}(((([^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]'’,\-\.\s])){1,})(['’\-,\.]){0,1}){2,}((([^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]'’,\-\.\s])){2,})?)*)$/;

HTML5:

<input type="text" name="full_name" id="full_name" pattern="^(?:((([^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]'’,\-.\s])){1,}(['’,\-\.]){0,1}){2,}(([^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]'’,\-. ]))*(([ ]+){0,1}(((([^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]'’,\-\.\s])){1,})(['’\-,\.]){0,1}){2,}((([^0-9_!¡?÷?¿/\\+=@#$%ˆ&*(){}|~<>;:[\]'’,\-\.\s])){2,})?)*)$" required>


0

Questo sembra fare il lavoro per me:

[\S]{2,} [\S]{2,}( [\S]{2,})*

-1

Una semplice funzione che utilizza preg_match in php

<?php
function name_validation($name) {
    if (!preg_match("/^[a-zA-Z ]*$/", $name) === false) {
        echo "$name is a valid name";
    } else {
        echo "$name is not a valid name";
    }
}

//Test
name_validation('89name');
?>


-2

Se vuoi che il nome intero sia compreso tra 3 e 30 caratteri senza restrizioni su singole parole, prova questo:

[a-zA-Z ]{3,30}

Attenzione che esclude tutte le lettere straniere come é, è, à, ï.

Se vuoi applicare il limite da 3 a 30 caratteri a ogni singola parola, Jens regexp farà il lavoro.


-2
var name = document.getElementById('login_name').value; 
if ( name.length < 4  && name.length > 30 )
{
    alert ( 'Name length is mismatch ' ) ;
} 


var pattern = new RegExp("^[a-z\.0-9 ]+$");
var return_value = var pattern.exec(name);
if ( return_value == null )
{
    alert ( "Please give valid Name");
    return false; 
} 
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.