Определить IBAN в тексте
Существует простой шаблон регулярных выражений, который обнаруживает IBAN в тексте (включая форматирование конкретной страны?)
На самом деле я нахожу IBAN с этим регулярным выражением:
[a-zA-Z]{2}[0-9]{2}[0-9a-zA-Z]{10,30}
Но это не соответствует форматированному IBAN, как (обычно, я не вводил обнаружение пробелов):
FR76 30003 02420 002202XXXXX 77
или же
PT50 0002 0123 1234 5678 9015 4
Вы можете мне помочь? Где я могу найти все отформатированные шаблоны IBAN по странам?
Пример:
"Мой IBAN - PT50 0002 0123 1234 5678 9015 1, поймайте его с помощью регулярного выражения, и это тоже PT50000201231234567890151!"
Я хотел бы извлечь / обработать "PT50 0002 0123 1234 5678 9015 1" и "PT50000201231234567890151".
Изменить: Решение 1 - Очень длинный шаблон:
((NO)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{3}|(NO)[0-9A-Z]{13}|(BE)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}|(BE)[0-9A-Z]{14}|(DK|FO|FI|GL|NL)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{2}|(DK|FO|FI|GL|NL)[0-9A-Z]{16}|(MK|SI)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{3}|(MK|SI)[0-9A-Z]{17}|(BA|EE|KZ|LT|LU|AT)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}|(BA|EE|KZ|LT|LU|AT)[0-9A-Z]{18}|(HR|LI|LV|CH)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{1}|(HR|LI|LV|CH)[0-9A-Z]{19}|(BG|DE|IE|ME|RS|GB)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{2}|(BG|DE|IE|ME|RS|GB)[0-9A-Z]{20}|(GI|IL)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{3}|(GI|IL)[0-9A-Z]{21}|(AD|CZ|SA|RO|SK|ES|SE|TN)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}|(AD|CZ|SA|RO|SK|ES|SE|TN)[0-9A-Z]{22}|(PT)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{1}|(PT)[0-9A-Z]{23}|(IS|TR)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{2}|(IS|TR)[0-9A-Z]{24}|(FR|GR|IT|MC|SM)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{3}|(FR|GR|IT|MC|SM)[0-9A-Z]{25}|(AL|CY|HU|LB|PL)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}|(AL|CY|HU|LB|PL)[0-9A-Z]{26}|(MU)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{2}|(MU)[0-9A-Z]{28}|(MT)[0-9A-Z]{2}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{4}[ ][0-9A-Z]{3}|(MT)[0-9A-Z]{29})
И не работает для французского конкретного шаблона.
2 ответа
Используемое регулярное выражение неверно для действительных IBAN. Используйте это регулярное выражение вместо
[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}([a-zA-Z0-9]?){0,16}
Источник: http://snipplr.com/view/15322/iban-regex-all-ibans/
Для получения дополнительной информации о формате IBAN:
https://en.wikipedia.org/wiki/International_Bank_Account_Number
Редактировать:
Для более сложного валидатора, проверьте этот код https://jsfiddle.net/kf332bhj/1/
Для обработки пробелов определите страну и определите регулярное выражение на основе длины символа
Проверьте последние стандарты IBAN от SWIFT
https://www.swift.com/standards
https://www.swift.com/standards/data-standards/iban
var CODE_LENGTHS = {
AD: 24, AE: 23, AT: 20, AZ: 28, BA: 20, BE: 16, BG: 22, BH: 22, BR: 29,
CH: 21, CR: 21, CY: 28, CZ: 24, DE: 22, DK: 18, DO: 28, EE: 20, ES: 24,
FI: 18, FO: 18, FR: 27, GB: 22, GI: 23, GL: 18, GR: 27, GT: 28, HR: 21,
HU: 28, IE: 22, IL: 23, IS: 26, IT: 27, JO: 30, KW: 30, KZ: 20, LB: 28,
LI: 21, LT: 20, LU: 20, LV: 21, MC: 27, MD: 24, ME: 22, MK: 19, MR: 27,
MT: 31, MU: 30, NL: 18, NO: 15, PK: 24, PL: 28, PS: 29, PT: 25, QA: 29,
RO: 24, RS: 22, SA: 24, SE: 24, SI: 19, SK: 24, SM: 27, TN: 24, TR: 26
};
Изменить 2:
Чтобы ответить Инго Леонхардту, проверьте реестр IBAN (PDF) по https://www.swift.com/standards/data-standards/iban
а) Норвегия имеет минимальный BBAN 11
b) Для IBAN 9-15 должны быть только числовыми ([0-9]{7}). Например, KZ86 125K ZT50 0410 0100 действует для Казахстана
Разумно было бы разбить решение на 2 шага:
- Найдите подозреваемых в тексте;
- Проанализируйте и (необязательно) подтвердите каждого подозреваемого.
Вот реализация такого подхода. Нам понадобится список длин IBAN для каждой страны. В моем случае список стран был очень ограничен, поэтому я использую тот, что из ответа @Sully здесь. Настоятельно рекомендуется получить самый последний список, поскольку к нему могут присоединиться другие страны.
const CODE_LENGTHS = {
AD: 24, AE: 23, AT: 20, AZ: 28, BA: 20, BE: 16, BG: 22, BH: 22, BR: 29,
CH: 21, CR: 21, CY: 28, CZ: 24, DE: 22, DK: 18, DO: 28, EE: 20, ES: 24,
FI: 18, FO: 18, FR: 27, GB: 22, GI: 23, GL: 18, GR: 27, GT: 28, HR: 21,
HU: 28, IE: 22, IL: 23, IS: 26, IT: 27, JO: 30, KW: 30, KZ: 20, LB: 28,
LI: 21, LT: 20, LU: 20, LV: 21, MC: 27, MD: 24, ME: 22, MK: 19, MR: 27,
MT: 31, MU: 30, NL: 18, NO: 15, PK: 24, PL: 28, PS: 29, PT: 25, QA: 29,
RO: 24, RS: 22, SA: 24, SE: 24, SI: 19, SK: 24, SM: 27, TN: 24, TR: 26
};
// We use a regexp to find the suspects.
// IBAN starts from a 2-character country code followed by the checksum.
// So 4 symbols + the country specific number.
// The longest IBAN in this case is 31 symbols
// so the IBAN 'tail' is 31 - 4 = 27 characters.
const MAX_LENGTH = Math.max(...Object.values(CODE_LENGTHS)) - 4;
// Let's say we want to highlight all the IBANs in the text.
const HighlightIBAN = text => text.replace(
// Here is the magic. We search 2 letters followed by 2 digits
// and followed by 27 meaningful characters.
// The group (?:\W*[a-z0-9]) allows to ignore spaces, dots,
// dashes or whatever a user may put as number group separators.
new RegExp('[a-z]{2}[0-9]{2}(?:\\W*[a-z0-9]){0,' + MAX_LENGTH + '}', 'ig'),
suspect => {
// Here we have our suspect.
// Just need to check if the IBAN is a IBAN indeed.
const country = suspect.substr(0, 2).toUpperCase();
const length = CODE_LENGTHS[country];
// If the first 2 letters isn't a country code (not in the list)
// we ignore the string found by the regex
if(!length) return suspect;
// Now we check if the finding contains the exact number
// of meaningful symbols and extract the IBAN
// using the same approach to ignore formatting
const checkRegexp = new RegExp('^((?:\\W*[a-z0-9]){' + length + '})(.*)$', 'i');
const parts = checkRegexp.exec(suspect);
// Nothing extracted. The suitable sequence of symbols not found.
// So we ignore the suspect again.
if(!parts) return suspect;
const iban = parts[1];
const tail = parts[2];
// We have our IBAN here.
// The 'tail' is the symbols which follow the IBAN.
// As we always pick 31 characters the string found
// will have several symbols which shouldn't be touched at the end.
// The extracted IBAN can be validated here (e.g. checksum and stuff)
// like @Sully suggested.
// Then we do our job. E.g. we can highlight the IBAN found.
// Just don't forget to put the 'tail' back.
return `<span class="iban">${iban}</span>${tail}`;
}
)
Пример использования можно найти здесь: https://jsfiddle.net/qkwx5ja7/1 .