我正在尝试从 BASIC 代码中提取 GOTOs/GOSUBs 行号。我打算使用 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
外,所有匹配组均正常,它仅返回第一个和最后一个数字(10000 和 800),而不返回其他数字。
我错过了什么?谢谢:)
最佳答案
无法使用正则表达式进行任意数量的捕获,也无法使用 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)] );
}
关于javascript - 使用 Regex 提取 GOTO/GOSUB 的行号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46151114/