You are using ^
as delimiter? You probably want something more like:
'/^[a-z]{6}[0-9a-z]{2}([0-9a-z]{3})?\z/i'
Question
I wrote a regex for php function pregmatch which is like this:
^([a-zA-Z]){4}([a-zA-Z]){2}([0-9a-zA-Z]){2}([0-9a-zA-Z]{3})?$^
Now I need to check the consistency of an BIC string.
Something is wrong with it... it is always correct. And I have no idea why.
The code I use is something like this:
/**
* Checks the correct format from the
* @param string $bic
* @return boolean
*/
public function checkBic($bic)
{
$bic = $this->cleanFromSeparators($bic);
if (preg_match($this->getBicCompare(), $bic)) {
return true;
} else {
return false;
}
}
private function getBicCompare()
{
return "^([a-zA-Z]){4}([a-zA-Z]){2}([0-9a-zA-Z]){2}([0-9a-zA-Z]{3})?$^";
}
EDIT:
Here are some references for BIC format from the swift account:
http://www.sage.co.uk/sage1000v2_1/form_help/workingw/subfiles/iban_and_bic.htm
http://en.wikipedia.org/wiki/ISO_9362
http://www.swift.com/products_services/bic_and_iban_format_registration_bic_details?rdct=t
an example BIC would be:
NOLADE21STS
OPSKATWW
The regex should only return true if the string consists of the following code: its length is eight or eleven characters and that consists of:
Bank code - 4 alphabetic characters Country code - 2 letters Location code - 2 alphanumeric characters, except zero Branch code - 3 alphanumeric characters
These are the specifications.
So the length can be either 11 or 8, first 4 can be anything, then 2 letters is a must, then 2 numbers and optional 3 alphanumeric.
The following are not valid:
abcdefxx
abcdefxxyyy
These also are not valid:
aaaa11xx
aaaa11xxyyy
and so on.
Solution
You are using ^
as delimiter? You probably want something more like:
'/^[a-z]{6}[0-9a-z]{2}([0-9a-z]{3})?\z/i'
OTHER TIPS
Structure
The latest edition is ISO 9362:2009 (dated 2009-10-01). The SWIFT code is 8 or 11 characters, made up of:
4 letters: Institution Code or bank code.
2 letters: ISO 3166-1 alpha-2 country code
2 letters or digits: location code
if the second character is "0", then it is typically a test BIC as opposed to a BIC used on the live network. if the second character is "1", then it denotes a passive participant in the SWIFT network if the second character is "2", then it typically indicates a reverse billing BIC, where the recipient pays for the message as opposed to the more usual mode whereby the sender pays for the message.
3 letters or digits: branch code, optional ('XXX' for primary office)
(http://en.wikipedia.org/wiki/ISO_9362)
(different definition in German-Wiki http://de.wikipedia.org/wiki/ISO_9362)
2 letters or digits: location code The first character must not be the digit "0" or "1". The letter 'O' is not allowed as a second character. (Regex for this definition: [2-9a-z][0-9a-np-z])
'/^[a-z]{6}[2-9a-z][0-9a-np-z]([a-z0-9]{3}|x{3})?$/i'
This is the official SEPA pattern for validating BIC
[A-Z]{6,6}[A-Z2-9][A-NP-Z0-9]([A-Z0-9]{3,3}){0,1}
I think this one would do:
/^[a-z0-9]{4}[a-z]{2}\d{2}([a-z0-9]{3})?$/
That is:
^
[a-z0-9]{4}
\d{2}
?
suffix) alphanumerich chars, ([a-z0-9]{3})?
$
You can see it in action and test it here (I used your samples).
Anyway, from the rules you are reporting, OPSKATWW
shouldn't be a valid BIC since it has no numbers after the first 6 letters.
echo preg_match('/^[A-Z]{4}(AC|AD|AE|AF|AG|AI|AL|AM|AN|AO|AQ|AR|AS|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BJ|BL|BM|BN|BO|BQ|BR|BS|BT|BV|BW|BY|BZ|CA|CC|CD|CE|CF|CG|CH|CI|CK|CL|CM|CN|CO|CP|CR|CS|CU|CV|CW|CX|CY|CZ|DD|DE|DG|DJ|DK|DM|DO|DZ|EA|EC|EE|EG|EH|ER|ES|ET|EU|FI|FJ|FK|FM|FO|FR|FX|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|IC|ID|IE|IL|IM|IN|IO|IQ|IR|IS|IT|JE|JM|JO|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MF|MG|MH|MK|ML|MM|MN|MO|MP|MQ|MR|MS|MT|MU|MV|MW|MX|MY|MZ|NA|NC|NE|NF|NG|NI|NL|NO|NP|NR|NT|NU|NZ|OM|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SF|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|SS|ST|SU|SV|SX|SY|SZ|TA|TC|TD|TF|TG|TH|TJ|TK|TL|TM|TN|TO|TP|TR|TT|TV|TW|TZ|UA|UG|UK|UM|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|XK|YE|YT|ZA|ZM|ZR|ZW)[2-9A-Z][0-9A-NP-Z]([A-Z0-9]{3}|x{3})?$/',$val);
I do not recommend using this as it's lacking performance, but in case someone needs to verify IBANS also against ISO-3366-1 country codes:
/^[A-Z]{4}(AC|AD|AE|AF|AG|AI|AL|AM|AN|AO|AQ|AR|AS|AT|AU|AW|AX|AZ|BA|BB|BD|BE|BF|BG|BH|BI|BJ|BL|BM|BN|BO|BQ|BR|BS|BT|BV|BW|BY|BZ|CA|CC|CD|CE|CF|CG|CH|CI|CK|CL|CM|CN|CO|CP|CR|CS|CU|CV|CW|CX|CY|CZ|DD|DE|DG|DJ|DK|DM|DO|DZ|EA|EC|EE|EG|EH|ER|ES|ET|EU|FI|FJ|FK|FM|FO|FR|FX|GA|GB|GD|GE|GF|GG|GH|GI|GL|GM|GN|GP|GQ|GR|GS|GT|GU|GW|GY|HK|HM|HN|HR|HT|HU|IC|ID|IE|IL|IM|IN|IO|IQ|IR|IS|IT|JE|JM|JO|JP|KE|KG|KH|KI|KM|KN|KP|KR|KW|KY|KZ|LA|LB|LC|LI|LK|LR|LS|LT|LU|LV|LY|MA|MC|MD|ME|MF|MG|MH|MK|ML|MM|MN|MO|MP|MQ|MR|MS|MT|MU|MV|MW|MX|MY|MZ|NA|NC|NE|NF|NG|NI|NL|NO|NP|NR|NT|NU|NZ|OM|PA|PE|PF|PG|PH|PK|PL|PM|PN|PR|PS|PT|PW|PY|QA|RE|RO|RS|RU|RW|SA|SB|SC|SD|SE|SF|SG|SH|SI|SJ|SK|SL|SM|SN|SO|SR|SS|ST|SU|SV|SX|SY|SZ|TA|TC|TD|TF|TG|TH|TJ|TK|TL |TM|TN|TO|TP|TR|TT|TV|TW|TZ|UA|UG|UK|UM|US|UY|UZ|VA|VC|VE|VG|VI|VN|VU|WF|WS|XK|YE|YT|ZA|ZM|ZR|ZW)[2-9A-Z][0-9A-NP-Z](XXX|[0-9A-WYZ][0-9A-Z]{2})?$/i
Also this is content validation and not just format validation. But it will save you a bit of code :)
Ok. to all who have the same problems with this kind of problem the correct regex is:
/^[0-9a-z]{4}[a-z]{2}[0-9a-z]{2}([0-9a-z]{3})?\z/i
thy @Qtax for providing it. i just refined it a bit.
Edit the tweak was that i changed it so the first 4 letters can be alphanumeric, but the 2 letters after it have to represent a international code for a country. That is why only letters. And i checked it with actual users who have real use codes. They can have numeric values in first 4 positions.
Edit:
I was in wrong. the firtst 4 cann be only letters. I was relaying on an statment of a employe from Reifeisen Bank with wich i was discussing the standard. It turner out he was thinking the number of the bank from their internal no idea what system cann be a valid code. As it turned out that is not the case.
So the correct sintax is
/^{6}[a-z]{2}[0-9a-z]{2}([0-9a-z]{3})?\z/i
Will mark the correct answer. Thank you for pointing it out.