我正在尝试从编码的二维条码中提取数据。提取部分工作正常,我可以在文本输入中获取值。
,例如,解码后的字符串是
] D2的 01 05000456013482的 17 201200的 10 00001 /:的 21 0000000001
基于以下规则(无法获得正确的表格标记,从而附加图片),我试图从上面提到的字符串中提取子字符串。
我想提取的子字符串:
05000456013482(在分隔符01之后)
201200(在分隔符17之后)
<00> 00001(在分隔符10之后)0000000001(在分隔符21之后)
P.S - &gt;原始字符串中的前3个字符(]d2
)总是相同的,因为它只是简单地表示解码方法。
现在有些怪癖:
1)分隔符10
后面的字母数不固定。因此,在上面给出的示例中,即使它是00001
,它也可能是001
。类似地,分隔符21
之后的字母数也不固定,并且可以具有不同的长度。
对于不同长度的分隔符,我添加了一个常量/:
,以确定在扫描手持设备后编码何时结束。
现在,我在分隔符10之后查找/:
并提取字符串,直到它到达/:
或EOL并找到分隔符21并删除字符串,直到它到达/:
或EOL
2)分隔符01
和17
后的字母数始终是固定的(分别为14个字母和6个字母),如表所示。
注意:分隔符的位置可能会发生变化。换句话说,编码的条形码可以用不同的顺序编写。
] d2 01 05000456013482 17 201200 10 00001 /: 21 0000000001 - 注意:否{{1因为它是EOL
,所以在21组之后签名] d2 17 201200 10 00001 /: 21 0000000001 /: 01 05000456013482 - 注意:两者均为10和21组有/:
符号表示我们必须提取,直到该符号
] d2 10 00001 /: 21 0000000001 /: 01 05000456013482 17 201200 - 前两个是长度变化,接下来两个是固定长度。
我不是正则表达式的专家,到目前为止我只尝试使用像/.
这样的简单模式,这些模式在给定的示例中不起作用,因为它像前两个字符一样查找10。此外,使用(01)(\d*)(21)(\d*)(10)(\d*)(17)(\d*)$
方法仅适用于固定长度字符串的情况,当我知道我必须采用哪些索引时。
P.S - 赞赏JS和jQuery帮助。
答案 0 :(得分:1)
好的,这是我对此的看法。我创建了一个匹配所有可能模式的正则表达式。这样,所有部件都被正确拆分,剩下的就是使用前两位数字来了解它的含义。
^\]d2(?:((?:10|21)[a-zA-Z0-9]{1,20}(?:\/:|$))|(01[0-9]{14})|((?:11|15|17)[0-9]{6}))*
我建议你把它复制到regex101.com来阅读完整的描述符并根据不同的可能结果进行测试。
有3个电源部分:
((?:10|21)[a-zA-Z0-9]{1,20}(?:\/:|$))
对从10和21开始的部分进行哪些测试。它查找1到20次之间的字母数字实体。它应以EOL
或/:
(01[0-9]{14})
查找GTIN,非常简单。
((?:11|15|17)[0-9]{6})
查找3个日期字段。
由于我们预计这三个细分市场会以任何顺序排列,我会将它们粘在一起暗示一个OR
并期望这个大序列重复(最后*
表示0或更多,我们可以定义确切的最小值和最大值以获得更高的可靠性)
我不确定这是否适用于所有内容,因为您提供的测试字符串不包含实际值中的标识符...很可能恰好在产品的最佳日期之前是1月,因此其中将有一个01值。但是强制正则表达式以这种方式执行应该可以避免其中的一些问题。
编辑:捕获组只捕获最后一次出现,因此我们需要拆分它们的定义:
^\]d2(?:(21[a-zA-Z0-9]{1,20}(?:\/:|$))|(10[a-zA-Z0-9]{1,20}(?:\/:|$))|(01[0-9]{14})|(11[0-9]{6})|(15[0-9]{6})|(17[0-9]{6}))*
再次编辑:Javascript似乎让我们感到头痛......我不确定处理它的正确方法,但这里有一个可行的示例代码。
var str = "]d20105000456013482172012001000001/:210000000001";
var r = new RegExp("(21[a-zA-Z0-9]{1,20}(?:\/:|$))|(10[a-zA-Z0-9]{1,20}(?:\/:|$))|(01[0-9]{14})|(11[0-9]{6})|(15[0-9]{6})|(17[0-9]{6})", "g");
var i = 0;
while ((match = r.exec(str)) != null) {
console.log(match[0]);
}
我对它的结果并不十分满意。可能有更好的解决方案。
答案 1 :(得分:1)
虽然您可以尝试制作一个非常复杂的正则表达式来执行此操作,但是在步骤中解析字符串会更具可读性和可维护性。
基本步骤是:
现在,由于您有一个AI /数据结构表,您可以使用几种方法来提取不同形式的数据
例如,由于AI:01,11,15,17都是固定长度,你可以使用长度为
的字符串切片方法str.slice(0,14); //for 01
str.slice(0,6); //for 11 15 17
虽然像AI 21这样的可变类似于
var fnc1 = "/:";
var fnc1Index = str.indexOf(fnc1);
str.slice(0,fnc1Index);
演示
var dataNames = {
'01': 'GTIN',
'10': 'batchNumber',
'11': 'prodDate',
'15': 'bestDate',
'17': 'expireDate',
'21': 'serialNumber'
};
var input = document.querySelector("input");
document.querySelector("button").addEventListener("click",function(){
var str = input.value;
console.log( parseGS1(str) );
});
function parseGS1(str) {
var fnc1 = "/:";
var data = {};
//remove ]d2
str = str.slice(3);
while (str.length) {
//get the AI identifier: 01,10,11 etc
let aiIdent = str.slice(0, 2);
//get the name we want to use for the data object
let dataName = dataNames[aiIdent];
//update the string
str = str.slice(2);
switch (aiIdent) {
case "01":
data[dataName] = str.slice(0, 14);
str = str.slice(14);
break;
case "10":
case "21":
let fnc1Index = str.indexOf(fnc1);
//eol or fnc1 cases
if(fnc1Index==-1){
data[dataName] = str.slice(0);
str = "";
} else {
data[dataName] = str.slice(0, fnc1Index);
str = str.slice(fnc1Index + 2);
}
break;
case "11":
case "15":
case "17":
data[dataName] = str.slice(0, 6);
str = str.slice(6);
break;
default:
console.log("unexpected ident encountered:",aiIndent);
return false;
break;
}
}
return data;
}
&#13;
<input><button>Parse</button>
&#13;