我需要一个正则表达式来匹配一个值,其中每个字符可以是从 0 到 9 的数字或空格。该值必须恰好包含 11 位数字。
例如,它应该匹配格式为“012 345 678 90”或“01234567890”的值。
谁能帮我解决这个问题?
我需要一个正则表达式来匹配一个值,其中每个字符可以是从 0 到 9 的数字或空格。该值必须恰好包含 11 位数字。
例如,它应该匹配格式为“012 345 678 90”或“01234567890”的值。
谁能帮我解决这个问题?
为了将来可能会发现这一点的其他澳大利亚开发人员:
^(\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.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:
从第一个(左)数字中减去 1,得到一个新的 11 位数字 将这个新数字中的每个数字乘以其权重因子 将得到的 11 个乘积相加。
将总数除以 89,注意余数。
如果余数为零,则该数字有效。
数字位置
1 2 3 4 5 6 7 8 9 10 11
重量
10 1 3 5 7 9 11 13 15 17 19
例如,检查 ABN 53 004 085 616 的有效性
5 3 0 0 4 0 8 5 6 1 6
从第一个(左)数字减去 1 得到新数字 4 3 0 0 4 0 8 5 6 1 6
应用加权因子 10 1 3 5 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# 验证:
public static bool ValidateABN(string abn)
{
bool isValid = false;
int[] weight = { 10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19 };
int weightedSum = 0;
//ABN must not contain spaces, comma's or hypens
abn = StripNonDigitData(abn);
//ABN must be 11 digits long
if (!string.IsNullOrEmpty(abn) & Regex.IsMatch(abn, "^\\d{11}$"))
{
//Rules: 1,2,3
for (int i = 0; i <= weight.Length - 1; i++)
{
weightedSum += (int.Parse(abn[i].ToString()) - ((i == 0 ? 1 : 0))) * weight[i];
}
//Rules: 4,5
return ((weightedSum % 89) == 0);
}
return isValid;
}
public static string StripNonDigitData(string input)
{
StringBuilder output = new StringBuilder("");
foreach (char c in input)
{
if (char.IsDigit(c))
{
output.Append(c);
}
}
return output.ToString();
}
和一个 VB.Net 验证:
Public Shared Function ValidateABN(ByVal abn As String) As Boolean
Dim isValid As Boolean = False
Dim weight() As Integer = {10, 1, 3, 5, 7, 9, 11, 13, 15, 17, 19}
Dim weightedSum As Integer = 0
'ABN must not contain spaces, comma's or hypens
abn = StripNonDigitData(abn)
'ABN must be 11 digits long
If Not String.IsNullOrEmpty(abn) And Regex.IsMatch(abn, "^\d{11}$") Then
'Rules: 1,2,3
For i As Integer = 0 To weight.Length - 1
weightedSum += (Integer.Parse(abn(i).ToString()) - (IIf(i = 0, 1, 0))) * weight(i)
Next
'Rules: 4,5
Return ((weightedSum Mod 89) = 0)
End If
Return isValid
End Function
Public Shared Function StripNonDigitData(ByVal input As String) As String
Dim output As New StringBuilder("")
For Each c As Char In input
If Char.IsDigit(c) Then
output.Append(c)
End If
Next
Return output.ToString
End Function
// 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;
}
另一个 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'));
你读过正则表达式吗?这很简单。
^[0-9 ]+$
对于那些使用 AngularJS 的人,我编写了一个指令来进行 ABN 验证:
var app = angular.module("demoapp", ["input-abn-directive"]);
和
<input type="abn" name="inputAbn" ng-model="modelAbn">
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;
}
回答问题
很多答案将包括正则表达式[0-9]{11}
或类似的,这对于大多数情况来说已经足够了,但是没有一个答案考虑到 ABN 不能以零开头的事实。
可用于确定 ABN 的最简单的正则表达式是:^\s*[1-9](\s*\d){10}\s*$
.
标准格式
标准数字格式是 2,3,3,3 位分组模式,前两位数字构成校验位,后 9 位是实际标识符。
用于专门检查此格式(带或不带空格)的正则表达式是^[1-9]\d(\s?\d{3}){3}$
.
number_format
使用 PHP函数可以很容易地模仿这种格式。
number_format( '12123123123', 0, '', ' ' ) === '12 123 123 123';
实际验证
与实际验证相关的任何其他答案都应该大部分有效,但不是 100%,除非有额外的检查以确保数字不以零开头。扩展当前评分最高的答案,只需要进行一项额外的检查。
if ( strlen( $abn ) === 11 && $abn[0] > 0 ) { // or $abn > 9999999999
// ...
}
已测试 ABN Javascript 实现
这些是有效的ABN:
这些是无效的ABN:
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(应该是有效的)
SQL Server 解决方案 - 在单个案例语句中
如其他答案中所述,单个正则表达式不太可能验证 ABN。下面的case
语句可以在 Microsoft SQL Server 中用于验证 ABN。您可能希望在包含 ABN 字段的表上创建一个持久计算列。根据下面的评论,如果您返回整数而不是文本描述,那么您可以使用这样的字段进行相对简单的比较:
允许您使用以下表达式:
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