Лучший способ буквенно-цифровой проверки в 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;     
   }

t0mcat
источник
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.

user113716
источник
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.

Neerajan
источник
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
Марк Баайдженс
источник