Код проверки номера VIN ColdFusion
Я пытаюсь преобразовать этот код проверки PHP в ColdFusion. Однако я не могу получить свою версию CF для правильной проверки VIN. Я надеюсь, что кто-то может пролить свет на то, что мне не хватает.
<cfscript>
function isVIN(v) {
var i = "";
var d = "";
var checkdigit = "";
var sum = 0;
var weights = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2];
var transliterations = {
a = 1,
b = 2,
c = 3,
d = 4,
e = 5,
f = 6,
g = 7,
h = 8,
j = 1,
k = 2,
l = 3,
m = 4,
n = 5,
p = 7,
r = 9,
s = 2,
t = 3,
u = 4,
v = 5,
w = 6,
x = 7,
y = 8,
z = 9
};
if (! REFindNoCase("^([\w]{3})[A-Z]{2}\d{2}([A-Z]{1}|\d{1})([\d{1}|X{1})([A-Z]+\d+|\d+[A-Z]+)\d{5}$", ARGUMENTS.v)) {
return false;
}
if (Len(ARGUMENTS.v) != 17) {
return false;
}
for (i = 1; i <= Len(ARGUMENTS.v); i++) {
d = Mid(ARGUMENTS.v, i, 1);
if (! isNumeric(d)) {
sum += transliterations[d] * weights[i];
} else {
sum += d * weights[i];
}
}
checkdigit = sum % 11;
if (checkdigit == 10) {
checkdigit = "x";
}
if (checkdigit == Mid(ARGUMENTS.v,8,1)) {
return true;
}
return false;
}
</cfscript>
(На CFLib.org есть функция проверки VIN, но она тоже не работает).
2 ответа
Ваша функция имеет две проблемы.
Во-первых, регулярное выражение неверно. Вот упрощенная рабочая версия:
^[A-Z\d]{3}[A-Z]{2}\d{2}[A-Z\d][\dX](?:[A-Z]+\d+|\d+[A-Z]+)\d{5}$
Примечание: согласно ответу Адама, существует более простая схема, чем эта.
Во-вторых, в вашем сравнении контрольных цифр Mid один - кажется, что 8 должно быть 9.
(Предположительно, это проблема преобразования языка из-за того, что PHP индексируется 0, а CFML - 1).
Если оба этих параметра исправлены, измененная функция возвращает значение true для VIN WAUBA24B3XN104537
(который является единственным образцом VIN, который я смог найти в быстром поиске).
На самом деле регулярное выражение немного не так. Я думаю, что @PeterBoughton исправил синтаксис, но на самом деле он не был действительным для поставленной задачи.
Вот пересмотренный раздел кода с подходящими комментариями:
var vinRegex = "(?x) ## allow comments
^ ## from the start of the string
## see http://en.wikipedia.org/wiki/Vehicle_Identification_Number for VIN spec
[A-Z\d]{3} ## World Manufacturer Identifier (WMI)
[A-Z\d]{5} ## Vehicle decription section (VDS)
[\dX] ## Check digit
[A-Z\d] ## Model year
[A-Z\d] ## Plant
\d{6} ## Sequence
$ ## to the end of the string
";
if (! REFindNoCase(vinRegex, arguments.v)) {
return false;
}
Это может быть значительно упрощено до следующего:
^[A-Z\d]{8}[\dX][A-Z\d]{2}\d{6}$
Использование любого из них также устраняет требование проверки длины, так как регулярное выражение будет применять это тоже.
Тестовый код для этой модификации:
for (vin in [
"1GNDM19ZXRB170064",
"1FAFP40634F172825"
]){
writeOutput("#vin#: #isVin(vin)#<br />");
}
Я собираюсь обновить CFLib подробной версией, так как легче понять, что происходит, и соединиться со спецификацией.