正则表达式匹配澳大利亚商业号码(ABN)

时间:2013-01-05 18:05:35

标签: regex

我需要一个正则表达式来匹配一个值,其中每个字符可以是0到9之间的数字或空格。该值必须包含11位数字。

例如,它应匹配“012 345 678 90”或“01234567890”格式的值。

有人可以帮我吗?

10 个答案:

答案 0 :(得分:17)

为了其他澳大利亚开发商的利益,将来可能会发现这一点:

^(\d *?){11}$

在每个数字后匹配11个数字,零个或多个空格。

编辑:

正如@ElliottFrisch所提到的,ABN还有一个适当验证的数学公式。使用正则表达式来正确验证ABN是非常困难的(或不可能的) - 尽管上述正则表达式至少匹配11位数字与间距。如果您正在进行实际验证,那么在这种情况下,正则表达式可能不适合您。

进一步阅读:

https://abr.business.gov.au/Help/AbnFormat

这是一个PHP实现:

http://www.clearwater.com.au/code

从上一页复制的代码,以防有一天它变得不可用:

//   ValidateABN
//     Checks ABN for validity using the published 
//     ABN checksum algorithm.
//
//     Returns: true if the ABN is valid, false otherwise.
//      Source: http://www.clearwater.com.au/code
//      Author: Guy Carpenter
//     License: The author claims no rights to this code.  
//              Use it as you wish.

function ValidateABN($abn)
{
    $weights = array(10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19);

    // strip anything other than digits
    $abn = preg_replace("/[^\d]/","",$abn);

    // check length is 11 digits
    if (strlen($abn)==11) {
        // apply ato check method 
        $sum = 0;
        foreach ($weights as $position=>$weight) {
            $digit = $abn[$position] - ($position ? 0 : 1);
            $sum += $weight * $digit;
        }
        return ($sum % 89)==0;
    } 
    return false;
}

我在这里找到的一个javascript:

http://www.mathgen.ch/codes/abn.html

答案 1 :(得分:3)

REF OLD DEAD LINK http://www.ato.gov.au/businesses/content.asp?doc=/content/13187.htm&pc=001/003/021/002/001&mnu=610&mfp=001/003&st=&cy=1

确认ABN

以下公式可用于验证您所分配的ABN,或验证向您处理的公司发放的ABN。

验证ABN:
从第一个(左)数字减去1,得到一个新的十一位数字 将此新数字中的每个数字乘以其加权因子 得到的11个产品总和 将总数除以89,注意余数 如果余数为零,则该数字有效。

数字位置
1 2 3 4 五 6 7 8 9 10 11

<强>重量
10 1 3 五 7 9 11 13 15 17 19

示例,检查ABN 53 004 085 616

的有效性

5 3 0 0 4 0 8 五 6 1 6

从第一个(左)数字减1以得到新数字 4 3 0 0 4 0 8 五 6 1 6

应用加权因子 10 1 3 五 7 9 11 13 15 17 19

(4x10)+(3x1)+(0x3)+(0x5)+(4x7)+(0x9)+(8x11)+(5x13)+(6x15)+(1x17)+(6x19) 40 + 3 + 0 + 0 + 28 + 0 + 88 + 65 + 90 + 17 + 114

445/89 = 5余数0

余数为零,因此数字有效。

这是一个C#验证:

<%= form_for @foo do |f| %>
  <!-- foo fields -->

  <%= f.fields_for :bars do |f_bar| %>
    <!-- bar fields of one bar -->
  <% end %>

  <!-- other foo fields -->

  <%= f.fields_for :bars do |f_bar| %>
    <!-- bar fields of another bar -->
  <% end %>

  <!-- The previous repeats many more times in a non predictable way -->

  <%= f.submit "Submit" %>
<% end %>

VB.Net验证:

bars

答案 2 :(得分:2)

// return false if not correct AU vat format
function ABNValidation (val) {
    val = val.replace(/[^0-9]/g, '');
    let weights = new Array(10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19);
    if (val.length === 11) { 
        let sum = 0;
        weights.forEach(function(weight, position) {
            let digit = val[position] - (position ? 0 : 1);
            sum += weight * digit;
        });
        return sum % 89 == 0;
    }
    return false;
}

答案 3 :(得分:1)

你读过正则表达式吗?这很简单。

^[0-9 ]+$

答案 4 :(得分:1)

对于那些使用AngularJS的人,我写了一个指令来进行ABN验证:

var app = angular.module("demoapp", ["input-abn-directive"]);

<input type="abn" name="inputAbn" ng-model="modelAbn">

https://github.com/jasadams/input-abn-directive

答案 5 :(得分:1)

另一个JavaScript版本:

/**
 * validate ABN
 * @param {string} abn
 * @return {boolean} is ABN number valid
 *    
 * 0. ABN must be 11 digits long
 * 1. Subtract 1 from the first (left) digit to give a new eleven digit number         
 * 2. Multiply each of the digits in this new number by its weighting factor         
 * 3. Sum the resulting 11 products         
 * 4. Divide the total by 89, noting the remainder         
 * 5. If the remainder is zero the number is valid  
 */
var validateABN = function(abn){

    var isValid = true;

    //remove all spaces
    abn = abn.replace(/\s/g, '');

    //0. ABN must be 11 digits long
    isValid &= abn && /^\d{11}$/.test(abn);

    if(isValid){

        var weightedSum = 0;
        var weight = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19];

        //Rules: 1,2,3  
        for (var i = 0; i < weight.length; i++) {
            weightedSum += (parseInt(abn[i]) - ((i === 0) ? 1 : 0)) * weight[i]; 
        }

        //Rules: 4,5                 
        isValid &= ((weightedSum % 89) === 0);
    }

    return isValid;
};

//tests
console.log(validateABN('51824753556'));
console.log(validateABN('51 824 753 556'));
console.log(validateABN('51824744556'));

答案 6 :(得分:0)

JavaScript版本:

function checkABN(str) {
    if (!str || str.length !== 11) {
        return false;
    }
    var weights = [10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19],
        checksum = str.split('').map(Number).reduce(
        function(total, digit, index) {
            if (!index) {
                digit--;
            }
            return total + (digit * weights[index]);
        },
        0
    );

    if (!checksum || checksum % 89 !== 0) {
        return false;
    }

    return true;
}

答案 7 :(得分:0)

问题答案

很多答案都将包含正则表达式[0-9]{11}或类似的词,这对于大多数情况是足够的,但是没有一个答案考虑到ABN不能以零开头的事实。

可用于确定ABN的最简单的正则表达式是^\s*[1-9](\s*\d){10}\s*$。该正则表达式考虑了正确的数字位数,任意数量的空格和非零前导数字。

标准格式

标准数字格式是2、3、3、3位分组模式,因为前两位构成校验位,其余9位是实际标识符。

用于专门检查此格式是否带空格的正则表达式为^[1-9]\d(\s?\d{3}){3}$

使用PHP number_format函数可以轻松模仿这种格式。

number_format( '12123123123', 0, '', ' ' ) === '12 123 123 123';

实际验证

与实际验证有关的其他答案中的任何一个都应该大部分是有效的,但不是100%,除非进行额外的检查以确保数字不以零开头。扩展当前评分最高的答案,只需再做一次检查即可。

if ( strlen( $abn ) === 11 && $abn[0] > 0 ) { // or $abn > 9999999999
    // ...
}

答案 8 :(得分:0)

经测试的ABN Javascript实现

这些是工作 ABN:

  • 33 051 775 556应该可以工作
  • 14 069 979 460应该可以工作
  • 24 302 976 253应该可以工作

这些是无效个ABN:

  • 65 065 987 968应该失败
  • 12 345 678 965应该失败
  function checkABN(value) {
      let weights = new Array(10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19);
      let abn = value.replace(/\D/g, ''); // strip non numeric chars
      if (abn.length != 11) {
          return false;
      }
      let abnFirstDigit = parseInt(abn.charAt(0)) - 1; //subtract 1 from first digit
      abn = abnFirstDigit + abn.substring(1); // replace first digit with the substracted value

      let total = 0;
      for (let i = 0; i < 11; i++)
          total += weights[i] * abn.charAt(i);

      if (total == 0 || total % 89 != 0) {
          return false;
      } else {
          return true;
      }
  }

http://www.mathgen.ch/codes/abn.html中的一个人有问题, 不允许使用14 069 979 460(应该是有效的)

答案 9 :(得分:0)

SQL Server解决方案-单个案例声明

如其他答案所述,单个正则表达式不太可能能够验证ABN。下面的case语句可以在Microsoft SQL Server中用于验证ABN。您可能想在包含ABN字段的表上创建一个持久化的计算列。根据下面的注释,如果返回整数而不是文本描述,则可以使用此类字段进行相对简单的比较:

  • 1 =有效
  • 0 =无效(长度错误)
  • -1 =无效(模式检查失败)

允许您使用以下表达式:

  • where abnValid = 1 -- match all valid records
  • where abnValid < 1 -- match all invalid records

以下验证ABN的逻辑基于杰里米·汤普森(Jeremy Thompson)在这里的回答。下面的语句冗长且效率低下-使其适合单个case语句,因此您可以将其与持久化的计算列一起使用-意味着性能提升将在更新时出现,而不是在选择时出现。假设您的abnColumn基于字符-因此,如果您使用的是数字类型,则添加一个显式的cast。它会忽略源数据中的空格字符,并假定ABN的第一个数字不为零。

    case 
        when len(ltrim(rtrim(replace(abnColumn,' ','')))) <> 11 then 'Wrong length' -- or perhaps 0
        when
        (
            ((try_cast(left(ltrim(rtrim(replace(abnColumn,' ',''))),1) as int)-1)*10) +
            (try_cast(left(right(ltrim(rtrim(replace(abnColumn,' ',''))),10),1) as int)*1) +
            (try_cast(left(right(ltrim(rtrim(replace(abnColumn,' ',''))),9),1) as int)*3) +
            (try_cast(left(right(ltrim(rtrim(replace(abnColumn,' ',''))),8),1) as int)*5) +
            (try_cast(left(right(ltrim(rtrim(replace(abnColumn,' ',''))),7),1) as int)*7) +
            (try_cast(left(right(ltrim(rtrim(replace(abnColumn,' ',''))),6),1) as int)*9) +
            (try_cast(left(right(ltrim(rtrim(replace(abnColumn,' ',''))),5),1) as int)*11) +
            (try_cast(left(right(ltrim(rtrim(replace(abnColumn,' ',''))),4),1) as int)*13) + 
            (try_cast(left(right(ltrim(rtrim(replace(abnColumn,' ',''))),3),1) as int)*15) + 
            (try_cast(left(right(ltrim(rtrim(replace(abnColumn,' ',''))),2),1) as int)*17) +
            (try_cast(right(ltrim(rtrim(replace(abnColumn,' ',''))),1) as int)*19)
        ) %89 <> 0 then 'Check pattern fail' -- or perhaps -1
        else 'Valid' -- or perhaps 1
    end as abnValidationCheck -- or perhaps abnValid