Il modo migliore per il controllo alfanumerico in Javascript


107

Qual è il modo migliore per eseguire un controllo alfanumerico su un INPUTcampo in JSP? Ho allegato il mio codice attuale

<script type="text/javascript">
  function validateCode(){
      var TCode = document.getElementById('TCode').value;
      for(var i=0; i<TCode.length; i++)
      {
        var char1 = TCode.charAt(i);
        var cc = char1.charCodeAt(0);

        if((cc>47 && cc<58) || (cc>64 && cc<91) || (cc>96 && cc<123))
        {

        }
         else {
         alert('Input is not alphanumeric');
         return false;
         }
      }
     return true;     
   }


2
Dipende da come definisci "migliore". La maggior parte delle risposte seguenti suggerisce regex, che è molto più lento del codice originale . Ho ripulito un po 'il tuo codice , che in realtà funziona molto bene.
Michael Martin-Smucker

Risposte:


100

Puoi usare questa regex /^[a-z0-9]+$/i


4
ovviamente questo presuppone che la stringa vuota ( "") non debba essere trovata.
zzzzBov

15
ñnon rientra nel modello tuttavia carattere UTF-8 completamente valido.
Oybek

8
/ ^ [a-z0-9] + $ / i.test (TCode)
Alex V

3
Il test di un'espressione regolare sembra essere molto più lento (66% in Chrome 36) rispetto a charCodeAt(). Vedi jsPerf e la mia risposta di seguito .
Michael Martin-Smucker

5
Questa regex non funziona con lettere di caratteri speciali utilizzate in alcune lingue, come "ą", "ź", "ć" ecc.
Rafał Swacha

79

L'inclinazione originale del richiedente all'uso str.charCodeAt(i)sembra essere più veloce dell'alternativa delle espressioni regolari. Nel mio test su jsPerf l'opzione RegExp è più lenta del 66% in Chrome 36 (e leggermente più lenta in Firefox 31).

Ecco una versione pulita del codice di convalida originale che riceve una stringa e restituisce trueo false:

function isAlphaNumeric(str) {
  var code, i, len;

  for (i = 0, len = str.length; i < len; i++) {
    code = str.charCodeAt(i);
    if (!(code > 47 && code < 58) && // numeric (0-9)
        !(code > 64 && code < 91) && // upper alpha (A-Z)
        !(code > 96 && code < 123)) { // lower alpha (a-z)
      return false;
    }
  }
  return true;
};

Naturalmente, potrebbero esserci altre considerazioni, come la leggibilità. Un'espressione regolare di una riga è decisamente più carina da guardare. Ma se sei strettamente interessato alla velocità, potresti prendere in considerazione questa alternativa.


17
I programmatori adorano l'aspetto del codice, ma tu ne vedi la bellezza interiore.
Ziggy

Interessante approccio alternativo - non mi è mai nemmeno passato per la mente. Sono venuto qui con in mente solo regex!
ozzy432836

La risposta che ti fa riflettere e ti fa capire cosa vuol dire "programmazione". Uso il tuo modo di pensare, nella mia risposta
Oscar Zarrus

42

Controllalo con una regex.

Le espressioni regolari JavaScript non hanno classi di caratteri POSIX, quindi devi scrivere manualmente gli intervalli di caratteri:

if (!input_string.match(/^[0-9a-z]+$/))
  show_error_or_something()

Qui ^significa l'inizio della stringa e $significa fine della stringa e [0-9a-z]+significa uno o più caratteri da 0a 9OR da aa z.

Maggiori informazioni su Javascript regexen qui: https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions


14
+1 per aver spiegato la regex di base e il collegamento a una guida, piuttosto che dare all'utente una "stringa magica".
Charles Burns

4
@inor puoi semplicemente aggiungere 'i' alla fine della regex per specificare l'insensibilità tra maiuscole e minuscole, .ie /^[a-z0-9]+$/ie questo coprirà sia lettere minuscole che maiuscole
LJH

33

Non è necessario farlo uno alla volta. Basta fare un test per quelli che non sono alfanumerici. Se ne viene trovato uno, la convalida non riesce.

function validateCode(){
    var TCode = document.getElementById('TCode').value;
    if( /[^a-zA-Z0-9]/.test( TCode ) ) {
       alert('Input is not alphanumeric');
       return false;
    }
    return true;     
 }

Se c'è almeno una corrispondenza di un non alfanumerico, lo farà return false.


6

Creerei un metodo di prototipo String:

String.prototype.isAlphaNumeric = function() {
  var regExp = /^[A-Za-z0-9]+$/;
  return (this.match(regExp));
};

Quindi, l'utilizzo sarebbe:

var TCode = document.getElementById('TCode').value;
return TCode.isAlphaNumeric()


2
DJDavid98: Non credo che la regola "non modificare gli oggetti che non possiedi" si applichi qui. Justin stava solo estendendo le capacità di String, non modificando le funzionalità esistenti. Per prospettiva, nel mondo C #, ciò sarebbe considerato come un utilizzo perfettamente valido di un metodo di estensione. Anche se un giorno "String.isAlphaNumeric (): boolean" fosse implementato dai produttori di browser, né la firma né l'azione cambierebbero effettivamente, quindi non vedo alcuna riduzione della manutenibilità in questo particolare esempio. Che qualcosa sia una regola non implica che non ci siano eccezioni.
Risto Välimäki

5
    // On keypress event call the following method
    function AlphaNumCheck(e) {
        var charCode = (e.which) ? e.which : e.keyCode;
        if (charCode == 8) return true;

        var keynum;
        var keychar;
        var charcheck = /[a-zA-Z0-9]/;
        if (window.event) // IE
        {
            keynum = e.keyCode;
        }
        else {
            if (e.which) // Netscape/Firefox/Opera
            {
                keynum = e.which;
            }
            else return true;
        }

        keychar = String.fromCharCode(keynum);
        return charcheck.test(keychar);
    }

Inoltre, questo articolo aiuta anche a comprendere la convalida alfanumerica JavaScript.


3

Scusatemi tutti, nessuna polemica. Ma affinché la comunità cresca come è cresciuta io in questi anni, è bene prendere appunti.

La vera stringa alfanumerica è come "0a0a0a0b0c0d"e non come "000000"o "qwertyuio".

Tutte le risposte che ho letto qui, sono tornate truein entrambi i casi. E perdonami, IMHO, questo non è giusto .

Se voglio controllare se la mia "00000"stringa è alfanum, la mia risposta "umana" è senza dubbio FALSA.

Perché? Semplice. Non riesco a trovare nessuna lettera char. Quindi, è una semplice stringa numerica [0-9].

D'altra parte, se volessi controllare la mia "abcdefg"stringa, la mia risposta "umana" è addirittura FALSA. Non vedo i numeri, quindi non è alfanumerico. Solo alfa [a-zA-Z].

La risposta di Michael Martin-Smucker è stata illuminante.

Tuttavia, mirava a ottenere prestazioni migliori invece di regex. Questo è vero, usando un modo di basso livello c'è una performance migliore. Ma i risultati sono gli stessi. Le stringhe "0123456789"(solo numeriche), "qwertyuiop"(solo alfa) e "0a1b2c3d4f4g"(alfanumeriche) restituiscono TRUEcome alfanumeriche. Stesso /^[a-z0-9]+$/imodo regex . Il motivo per cui la regex non funziona è tanto semplice quanto ovvio. La sintassi []indica o , non e . Quindi, se è solo numerico o se è solo lettere, regex restituisce true.

Tuttavia, la risposta di Michael Martin-Smucker è stata comunque illuminante. Per me. Mi ha permesso di pensare a "basso livello", di creare una vera funzione che processa in modo univoco una stringa alfanumerica. L'ho chiamata come funzione relativa di PHP ctype_alnum( modifica 2020-02-18: dove, tuttavia, questo controlla OR e non AND ).

Ecco il codice:

function ctype_alnum(str) {
  var code, i, len;
    var isNumeric = false, isAlpha = false; //I assume that it is all non-alphanumeric



  for (i = 0, len = str.length; i < len; i++) {
    code = str.charCodeAt(i);


        switch (true){
            case code > 47 && code < 58: // check if 0-9
                isNumeric = true;
                break;
            case (code > 64 && code < 91) || (code > 96 && code < 123): //check if A-Z or a-z
                isAlpha = true;
                break;
            default: // not 0-9, not A-Z or a-z
                return false; //stop function with false result, no more checks

        }

  }

  return isNumeric && isAlpha; //return the loop results, if both are true, the string is certainly alphanumeric
};

... ed ecco la DEMO

Sono arrivato a questa discussione perché cercavo un'alternativa in javascript alla funzione PHP. Non ho trovato la risposta "ready-to-go", ma come spesso accade su Stackoverflow, il concetto di conoscenza e confronto tra loro è qualcosa di sublime, che ti porta a pensare alla risposta di qualcuno e trovare insieme la soluzione che eri cercando, ma non pensavi di saperlo.

E condividilo!

Migliore

Oscar


Quanto sopra risolve alphaAndNumeric, non alphaNumeric. return isNumeric || isAlpha;è alphaNumeric. Quanto sopra può essere utile ad alcuni.
TamusJRoyce

1
@TamusJRoyce ovviamente. Ma l'immagine per controllare un numero di partita IVA dove in alcuni casi è solo numerico e in altri casi deve essere alfanumerico. A proposito, mi rendo conto solo ora, colpa mia, che la relativa funzione PHP prevede OR invece di AND. Il che è un problema perché ho dovuto modificare tutti i codici delle mie applicazioni PHP, creando una funzione ad-hoc che prevedeva l'AND
Oscar Zarrus il

3

In un ciclo stretto, probabilmente è meglio evitare regex e codificare i tuoi caratteri:

const CHARS = new Set("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
function isAlphanumeric(char) {
    return CHARS.has(char);
}

puoi spiegare questo
lazydeveloper

2
Questo codice è O (N ^ 2) durante la scansione di un'intera stringa in un ciclo e si tradurrà in prestazioni di gran lunga peggiori rispetto alle peggiori soluzioni regex presentate (ad esempio un utente passa tutte le 'Z, indexOf () deve scansionare al fine per ogni carattere). Non solo potrebbe sostenere l'overhead della scansione dell'intera stringa 0-Z (eseguendo, in media, 18 confronti di caratteri per chiamata) ma anche due chiamate di funzione che valgono l'overhead per carattere della stringa sorgente: un valore di tempo costante piuttosto significativo! Il codice potrebbe persino introdurre una vulnerabilità DoS a seconda di dove viene utilizzato.
CubicleSoft

1
Hai assolutamente ragione CubicleSoft. Ho aggiornato la risposta per utilizzare JS Set.
Malganis

0

Per verificare se input_string è alfanumerico, usa semplicemente:

input_string.match(/[^\w]|_/) == null
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.