Дизайн регулярного выражения IBAN

Помогите мне, пожалуйста, разработать регулярное выражение, которое будет сопоставлять все IBAN со всеми возможными пробелами. Потому что я нашел его, но он не работает с пробелами.

[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}([a-zA-Z0-9]?){0,16}

Мне нужны хотя бы такие форматы:

DE89 3704 0044 0532 0130 00
AT61 1904 3002 3457 3201
FR14 2004 1010 0505 0001 3

person Maximus    schedule 20.06.2017    source источник
comment
Вы пытались вставить ноль или один пробел в нужных местах? Не бойтесь, модифицированное регулярное выражение не взорвется, если вы немного повозитесь.   -  person Filburt    schedule 20.06.2017
comment
FWIW, это не подтверждает достоверность iban. Для этого нужно гораздо больше.   -  person baao    schedule 11.06.2018
comment
Хороший обширный список, который можно использовать, — это это из Apache Commons. Вы можете собрать все шаблоны, которые были определены, и адаптировать их для приема пробелов. Например: DE\d{2}\s*\d{4}\s*\d{4}\s*\d{4}\s*\d{4}\s*\d{2} будет соответствовать вашему первому примеру.   -  person Hannon Queiroz    schedule 21.12.2018
comment
Чтобы проверить IBAN со всеми возможными пробелами, просто удалите пробелы перед проверкой, это немного упрощает задачу. Но на самом деле вы просто не можете полностью проверить регулярное выражение, так как основным ключом для проверки является контрольная сумма.   -  person A.P.    schedule 27.11.2019
comment
Итак, чтобы проверить iban, я бы сделал: 1) нормализовал: преобразовал в верхний регистр и удалил все, кроме [A-Z0-9] 2) сопоставил шаблон [A-Z]{2}[0-9]{2}[A-Z0-9]{1,30} 3) проверил контрольную сумму. Кроме того, вы можете проверить длину (зависит от страны), но в большинстве случаев это не требуется, если вы не хотите исключить, что кто-то составил IBAN, пересчитав контрольную сумму.   -  person A.P.    schedule 27.11.2019
comment
Я просто хотел знать, может ли быть IBAN с пустыми пробелами или - между ... и, прочитав много сложных, неработающих регулярных выражений, я сделал это сам. Я решил поделиться этим: /(?<![A-Z])[A-Z]{2}(\h|\-)?[0-9]{2}(\h|\-)?[A-Z0-9](?:(\h|\-)?[A-Z0-9]){10,29}(?![A-Z0-9])/   -  person cottton    schedule 23.07.2021


Ответы (4)


Просто для примера IBAN из этих стран:
Начните с 2 букв, затем 2 цифр.
Затем оставьте пробел перед каждыми 4 цифрами, по желанию заканчивая 1 или 2 цифрами:

\b[A-Z]{2}[0-9]{2}(?:[ ]?[0-9]{4}){4}(?!(?:[ ]?[0-9]){3})(?:[ ]?[0-9]{1,2})?\b    

тестируйте regex101 здесь

Обратите внимание, что если вы хотите проверить всю строку, регулярное выражение можно упростить.
Поскольку отрицательный прогноз (?!...) тогда не понадобится.
И границы слов \b можно заменить началом ^ и конец $ строки.

^[A-Z]{2}[0-9]{2}(?:[ ]?[0-9]{4}){4}(?:[ ]?[0-9]{1,2})?$

Кроме того, это можно упростить еще больше, если наличие 4 групп по 4 соединенных цифры не имеет значения.

^[A-Z]{2}(?:[ ]?[0-9]){18,20}$

Примечания

Но если вы хотите сопоставить номер IBAN со всего мира?
Тогда часть IBAN BBAN может содержать до 30 цифр или букв верхнего регистра. Справочник
И может быть написан либо с пробелами, либо с дефисами, либо без пробелов.
Например: CC12 XXXX 12XX 1234 1234 1234 1234 1234 123

Таким образом, регулярное выражение для сопоставления строки с длинным IBAN станет немного длиннее.

^([A-Z]{2}[ \-]?[0-9]{2})(?=(?:[ \-]?[A-Z0-9]){9,30}$)((?:[ \-]?[A-Z0-9]{3,5}){2,7})([ \-]?[A-Z0-9]{1,3})?$

тестируйте regex101 здесь

Также обратите внимание, что чистое регулярное выражение не может выполнять вычисления.
Таким образом, для фактической проверки номера IBAN требуется дополнительный код.

Пример фрагмента кода Javascript:

function smellsLikeIban(str){
 return /^([A-Z]{2}[ \-]?[0-9]{2})(?=(?:[ \-]?[A-Z0-9]){9,30}$)((?:[ \-]?[A-Z0-9]{3,5}){2,7})([ \-]?[A-Z0-9]{1,3})?$/.test(str);
}

function validateIbanChecksum(iban) {       
  const ibanStripped = iban.replace(/[^A-Z0-9]+/gi,'') //keep numbers and letters only
                           .toUpperCase(); //calculation expects upper-case
  const m = ibanStripped.match(/^([A-Z]{2})([0-9]{2})([A-Z0-9]{9,30})$/);
  if(!m) return false;
  
  const numbericed = (m[3] + m[1] + m[2]).replace(/[A-Z]/g,function(ch){
                        //replace upper-case characters by numbers 10 to 35
                        return (ch.charCodeAt(0)-55); 
                    });
  //The resulting number would be to long for javascript to handle without loosing precision.
  //So the trick is to chop the string up in smaller parts.
  const mod97 = numbericed.match(/\d{1,7}/g)
                          .reduce(function(total, curr){ return Number(total + curr)%97},'');

  return (mod97 === 1);
};

var arr = [
 'DE89 3704 0044 0532 0130 00', // ok
 'AT61 1904 3002 3457 3201', // ok
 'FR14 2004 1010 0505 0001 3', // wrong checksum
 'GB82-WEST-1234-5698-7654-32', // ok
 'NL20INGB0001234567', // ok
 'XX00 1234 5678 9012 3456 7890 1234 5678 90', // smells ok
 'YY00123456789012345678901234567890', // smells ok
 'NL20-ING-B0-00-12-34-567', // wrong format, but valid checksum
 'XX22YYY1234567890123', // wrong checksum
 '[email protected]' // Not even smells like IBAN
];
arr.forEach(function (str) {
  console.log('['+ str +'] Smells Like IBAN:    '+ smellsLikeIban(str));
  console.log('['+ str +'] Valid IBAN Checksum: '+ validateIbanChecksum(str))
});

person LukStorms    schedule 20.06.2017
comment
Где вы видите 4-значный код банка в ваших регулярных выражениях? Примеры: NL20INGB0001234567 и GB82WEST12345698765432. - person hansmbakker; 11.06.2018
comment
@wind-rider Регулярные выражения были написаны в соответствии с форматами, которые задавал вопрос. Где некоторые цифры сгруппированы по 4. Но действительно, часть BBAN IBAN может иметь до 30 буквенно-цифровых символов, которые зависят от страны. - person LukStorms; 11.06.2018
comment
@wind-rider Для полноты картины я включил регулярное выражение для других IBAN. - person LukStorms; 11.06.2018
comment
@wind-rider После проверки википедии и тестирования ее на макетах из разных стран мне пришлось немного изменить регулярное выражение. И включил для него тест regex101. - person LukStorms; 11.06.2018
comment
хорошо, я проголосовал за ваш ответ :) - person hansmbakker; 11.06.2018
comment
@LukStorms, почему положительный прогноз в регулярном выражении по всему миру? ваш тест regex101 все еще работает без него - person Vituel; 10.07.2018
comment
@Vituel Чтобы гарантировать, что часть BBAN не содержит более 30 букв или цифр. См. определение IBAN. Если бы это зависело только от других групп, то BBAN с (5 * 6) + 3 все еще мог бы пройти. Regex касается не только того, что шаблон позволяет, но и того, что он не позволяет. - person LukStorms; 10.07.2018
comment
прежде всего, большое спасибо за это. Но согласно Википедии разрешены только заглавные буквы. - person Naryoril; 29.08.2018
comment
@Naryoril Хороший вопрос. На странице Википедии этого еще не было. Это было исправлено. И если кто-то все еще хочет разрешить использование строчных букв, он может просто добавить флаг i, чтобы игнорировать регистр. - person LukStorms; 29.08.2018
comment
Я заметил еще одну проблему, он правильно распознает AB0011112223333444455556666777788, но не AB00 1111 2222 3333 4444 5555 6666 7777 88. Вероятно, проблема с пробелами и максимальной длиной. - person Naryoril; 29.08.2018
comment
@Naryoril Спасибо за тщательное тестирование! Действительно, {2,6} пришлось заменить на {2,7}. Это не было проблемой для одного без пробелов, потому что тогда он соответствует группам по 5 цифрам. Но для одного с пробелами 6*4=24 должно было быть 7*4=28. Оно было обновлено. (Кстати, это мой старый ответ, и я был немного удивлен, что некоторые люди каким-то образом находят его в длинном списке вопросов SO) - person LukStorms; 29.08.2018
comment
ПопахиваетLikeIBAN, не ограничиваясь началом и концом строки: /(?<![A-Z])[A-Z]{2}(\h|\-)?[0-9]{2}(\h|\-)?[A-Z0-9](?:(\h|\-)?[A-Z0-9]){10,29}(?![A-Z0-9])/. Успешно протестировано с последним тестом @LukStorms regex101.com/r/dzDqmM/56 (включите g (Глобальный)) - person cottton; 23.07.2021

Вот предложение, которое может работать для предоставленных вами шаблонов:

[A-Z]{2}\d{2} ?\d{4} ?\d{4} ?\d{4} ?\d{4} ?[\d]{0,2}

Попробуйте на regex101


Пояснение

  • [A-Z]{2}\d{2} ? 2 заглавные буквы, за которыми следуют 2 цифры (необязательный пробел)
  • \d{4} ? 4 цифры, повторяющиеся 4 раза (необязательный пробел)
  • [\d]{0,2} от 0 до 2 цифр
person Mistalis    schedule 20.06.2017
comment
Это не позволит буквы после начала. Его существующий шаблон позволяет это. - person ssc-hrep3; 20.06.2017

Вы можете использовать регулярное выражение следующим образом:

^[A-Z]{2}\d{2} (?:\d{4} ){3}\d{4}(?: \d\d?)?$

Рабочая демонстрация

Это будет соответствовать только тем строковым форматам

person Federico Piazza    schedule 20.06.2017
comment
Спасибо, но это не работает, если вы удаляете пробелы. Что я имел в виду, я не могу понять, как обрабатывать любые позиции пробелов (включая отсутствие пробелов). - person Maximus; 20.06.2017
comment
@Maximus, регулярное выражение помогает вам сопоставлять шаблоны, если вам нужно сопоставлять произвольные символы, вам придется постоянно использовать проверку пробелов, например: [A-Z]\s*[A-Z]\s*\d\s*\d\s*.....etc. Ваш вопрос не ясен, вы должны обновить его и добавить больше описания с дополнительным образцом. Однако, если мой ответ отвечает на ваш вопрос, и вы просто хотите сделать пробелы необязательными, вам нужно просто добавить ? к каждому пробелу. - person Federico Piazza; 20.06.2017

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

^[a-zA-Z]{2}[0-9]{2}\s?[a-zA-Z0-9]{4}\s?[0-9]{4}\s?[0-9]{3}([a-zA-Z0-9]\s?[a-zA-Z0-9]{0,4}\s?[a-zA-Z0-9]{0,4}\s?[a-zA-Z0-9]{0,4}\s?[a-zA-Z0-9]{0,3})?$

Вот живой пример: https://regex101.com/r/ZyIPLD/1.

person ssc-hrep3    schedule 20.06.2017