我试图从BASIC代码中提取GOTO / GOSUB的行号。我打算使用NodeJS来管理匹配(所以它是JS风格的正则表达式)。
我正在使用regex101.com进行测试(请参阅此处https://regex101.com/r/SaZuue/2),而且我非常接近我想要的内容:
GOTO ###
提取为["GOTO", " ", "###"]
GOSUB ###
提取为["GOSUB", " ", "###"]
IF (cond) THEN ###
提取为["THEN", " ", "###"]
ON ERR GOTO #, ##, ###
提取为["GOTO", " ", "#", ", ", "##", ", ", "###"]
ON ERR GOSUB
GOTO
,GOSUB
,THEN
和,
之间的空格是可选的,或者可以是多个空格,并且在所有情况下都返回指示的确切空格数到目前为止,我已经提出了以下正则表达式:
/(GOTO|GOSUB|THEN)(\s*)(\d+)(?:(\s*,\s*)(\d+))*/ig
测试:
100 ON ERR GOTO 10000, 30, 200, 10,800: GOSUB 20: IF A THEN 10: GOTO30: GOTO 50
除了ON ERR GOTO
之外,所有匹配组都没问题,Allowed memory size of 2097152 bytes exhausted
只返回第一个和最后一个数字(10000和800),而不返回其他数字。
我错过了什么?谢谢:))
答案 0 :(得分:3)
使用正则表达式无法获得任意数量的捕获,并且无法使用JS RegExp访问单个组中的多个捕获,因为它不会为每个组存储捕获值堆栈(后续捕获重写现有的,因此,每组只存储最后一次捕获。)
捕获逗号分隔数字的条纹,然后拆分以分别获取它们。例如。使模式的结尾看起来像((?:\s*,\s*\d+)*)
(以匹配0+序列的,
,其中包含0+空格,后跟1+位数)然后,在匹配时,用/\s*,\s*/
分割并过滤。
参见JS演示:
var rx = /\b(GO(?:TO|SUB)|THEN)(\s*)(\d+)((?:\s*,\s*\d+)*)/gi;
var str = "100 ON ERR GOTO 10000, 30, 200, 10,800: GOSUB 20: IF A THEN 10: GOTO30: GOTO 50";
var m;
while ((m = rx.exec(str)) !== null) {
console.log( [m[1], m[2], m[3], m[4].split(/\s*,\s*/).filter(Boolean)] );
}