4

この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検証機能がありますが、どちらも機能しません)。

4

2 に答える 2

8

関数には2つの問題があります。

まず、正規表現が正しくありません。簡略化された作業バージョンは次のとおりです。

^[A-Z\d]{3}[A-Z]{2}\d{2}[A-Z\d][\dX](?:[A-Z]+\d+|\d+[A-Z]+)\d{5}$

注:Adamの回答によると、これよりも単純なパターンがあります。


次に、チェックディジットの比較では、ミッドは1つです。8は9である必要があるようです。

(おそらく、これは、CFMLが1インデックスであるのに対し、PHPは0インデックスであるため、言語変換の問題です。)


これらの両方を修正すると、変更された関数はVINに対してtrueを返しますWAUBA24B3XN104537(これは、クイック検索で見つけた唯一のサンプルVINです)。

于 2012-12-20T19:16:12.977 に答える
3

実際、正規表現はまだ少し間違っています。@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を冗長バージョンで更新します。

于 2012-12-20T20:18:10.467 に答える