Лучший способ буквенно-цифровой проверки в Javascript


107

Как лучше всего выполнить буквенно-цифровую проверку INPUTполя JSP? Я прикрепил свой текущий код

<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
Зависит от того, как вы определяете «лучший». В большинстве ответов ниже предлагается регулярное выражение, которое работает намного медленнее, чем исходный код . Я немного очистил ваш код , и он действительно работает очень хорошо.
Майкл Мартин-Смакер

Ответы:


100

Вы можете использовать это регулярное выражение /^[a-z0-9]+$/i


4
конечно , это предполагает , что это пустая строка ( "") не должны совпадать.
zzzzBov

15
ñне попадает в шаблон, однако является полностью действительным символом UTF-8.
Ойбек

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

3
Проверка регулярного выражения кажется намного медленнее (66% в Chrome 36), чем charCodeAt(). См. JsPerf и мой ответ ниже .
Майкл Мартин-Смакер

5
Это регулярное выражение не работает со специальными символами, используемыми в некоторых языках, таких как «ą», «ź», «ć» и т. Д.
Рафал Свача,

80

Изначальная склонность спрашивающего к использованию str.charCodeAt(i)оказывается быстрее, чем альтернатива регулярному выражению. В моем тесте на jsPerf параметр RegExp работает на 66% медленнее в Chrome 36 (и немного медленнее в Firefox 31).

Вот очищенная версия исходного кода проверки, который получает строку и возвращает trueили 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;
};

Конечно, могут быть другие соображения, например, удобочитаемость. Однострочное регулярное выражение определенно красивее. Но если вы строго озабочены скоростью, вы можете рассмотреть эту альтернативу.


17
Программистам нравится внешний вид кода, но вы видите его внутреннюю красоту.
Зигги

Интересный альтернативный подход - даже в голову не приходил. Я пришел сюда, имея в виду только регулярное выражение!
ozzy432836

Ответ, который заставляет задуматься и заставляет понять, что означает «программирование». Я использую ваш образ мышления в своем ответе
Оскар Заррус

42

Проверьте это с помощью регулярного выражения.

Регулярное выражение Javascript не имеет классов символов POSIX, поэтому вам придется писать диапазоны символов вручную:

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

Здесь ^означает начало строки и $означает конец строки, а также [0-9a-z]+означает один или несколько символов от 0до 9ИЛИ от aдо z.

Дополнительная информация о регулярном выражении Javascript здесь: https://developer.mozilla.org/en/JavaScript/Guide/Regular_Expressions


14
+1 для объяснения основного регулярного выражения и ссылки на руководство, вместо того, чтобы давать пользователю «волшебную строку».
Чарльз Бернс

4
@inor вы можете просто добавить 'i' в конце регулярного выражения, чтобы указать нечувствительность к регистру, .ie, /^[a-z0-9]+$/iи это будет охватывать как строчные, так и прописные буквы
LJH

33

Вам не нужно делать это по одному. Просто сделайте тест для всех, которые не являются буквенно-цифровыми. Если он найден, проверка не выполняется.

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

Если есть хотя бы одно совпадение не буквенно-цифрового символа, оно будет return false.


6

Я бы создал метод прототипа String:

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

Тогда использование будет следующим:

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


2
DJDavid98: Я не думаю, что здесь применимо правило «не изменяйте объекты, которыми вы не владеете». Джастин просто расширял возможности String, а не изменял существующие. С точки зрения перспективы, в мире C # это можно было бы рассматривать как совершенно допустимое использование метода расширения. Даже если когда-нибудь "String.isAlphaNumeric (): boolean" будет реализован производителями браузеров, ни подпись, ни действие на самом деле не изменится, поэтому я не вижу никакого снижения ремонтопригодности в этом конкретном примере. То, что что-то является правилом, не означает, что нет никаких исключений.
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);
    }

Кроме того, эта статья также помогает понять , буквенно - цифровую проверку JavaScript.


4

Простите меня, без споров. Но для того, чтобы сообщество росло так, как выросло меня за эти годы, хорошо сделать несколько заметок.

Настоящая буквенно-цифровая строка похожа, "0a0a0a0b0c0d"а не на "000000"или "qwertyuio".

Все ответы, которые я прочитал здесь, были возвращены trueв обоих случаях. И уж простите, ИМХО, это не правильно .

Если я хочу проверить, является ли моя "00000"строка буквенной, мой «человеческий» ответ, несомненно, ЛОЖНЫЙ.

Зачем? Просто. Я не могу найти ни одной буквы char. Итак, это простая числовая строка [0-9].

С другой стороны, если бы я хотел проверить свою "abcdefg"строку, мой «человеческий» ответ даже ЛОЖЬ. Я не вижу цифр, значит, они не буквенно-цифровые. Просто альфа [a-zA-Z].

В ответ Майкл Мартин-Смакер в была освещая.

Однако он был нацелен на достижение лучшей производительности вместо регулярного выражения. Это правда, использование низкоуровневого способа дает лучшую производительность. Но результат тот же. Строки "0123456789"(только числовые), "qwertyuiop"(только буквенные) и "0a1b2c3d4f4g"(буквенно-цифровые) возвращаются TRUEкак буквенно-цифровые. Тот же /^[a-z0-9]+$/iспособ регулярного выражения . Причина, по которой регулярное выражение не работает, настолько же проста, насколько очевидна. Синтаксис []указывает или , а не и . Итак, если это только число или только буквы, регулярное выражение возвращается true.

Но, тем не менее , ответ Майкла Мартина-Смакера прояснил . Для меня. Это позволило мне думать на «низком уровне», создать настоящую функцию, которая однозначно обрабатывает буквенно-цифровую строку. Я назвал это относительной функцией PHP ctype_alnum( отредактируйте 2020-02-18: где, однако, проверяется ИЛИ, а не И ).

Вот код:

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
};

... а вот ДЕМО

Я пришел к этому обсуждению, потому что искал в javascript альтернативу функции PHP. Я не нашел ответа «готов к работе», но, как это часто бывает в Stackoverflow, концепция знания и сравнения друг с другом - это нечто возвышенное, что заставляет вас думать о чьем-то ответе и вместе находить решение, которым вы были искал, но вы не думали, что знаете об этом.

И поделитесь этим!

Лучший

Оскар


Вышеупомянутое решает alphaAndNumeric, а не alphaNumeric. return isNumeric || isAlpha;является alphaNumeric. Вышеупомянутое может быть полезно для некоторых.
TamusJRoyce

1
@TamusJRoyce, конечно. Но изображение для проверки некоторого номера НДС, где в некоторых случаях это просто число, а в другом случае должно быть буквенно-цифровым. Кстати, только сейчас я по своей вине понимаю, что относительная функция PHP предусматривает OR вместо AND. Это проблема, потому что мне пришлось изменить все коды своих PHP-приложений, создав специальную функцию, которая обеспечивала AND
Оскар Заррус

3

В жестком цикле, вероятно, лучше избегать регулярных выражений и жестко кодировать ваши символы:

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

Вы можете это объяснить?
lazydeveloper

2
Этот код равен O (N ^ 2) при сканировании всей строки в цикле и приведет к гораздо худшей производительности, чем даже наихудшие из представленных решений регулярных выражений (например, пользователь передает все Z, indexOf () должен сканировать в конец для каждого персонажа). Это не только потенциально связано с накладными расходами на сканирование всей строки 0-Z (выполнение в среднем 18 сравнений символов за вызов), но также с накладными расходами на два вызова функций на символ исходной строки - довольно важное постоянное значение времени! Код может даже ввести DoS-уязвимость в зависимости от того, где он используется.
CubicleSoft

1
Вы абсолютно правы CubicleSoft. Я обновил ответ, чтобы использовать JS Set.
Мальганис

0

Чтобы проверить, является ли input_string буквенно-цифровым, просто используйте:

input_string.match(/[^\w]|_/) == null
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.