我正在尝试从 BASIC 代码中提取 GOTOs/GOSUBs 行号。我打算使用 NodeJS 来管理匹配(所以它是 JS-flavored Regex)。

我正在使用 regex101.com(见这里 https://regex101.com/r/SaZuue/2 )进行测试,我非常接近我想要的:

  • GOTO ### 提取为 ["GOTO", " ", "###"]
  • GOSUB ### 提取为 ["GOSUB", " ", "###"]
  • IF (cond) THEN ### 提取为 ["THEN", " ", "###"]
  • ON ERR GOTO #, ##, ### 提取为 ["GOTO", " ", "#", ", ", "##", ", ", "###"]
  • 与上面相同,但带有 ON ERR GOSUB
  • 处理这样一个事实,即 GOTOGOSUBTHEN, 之间的空格是可选的,也可以是多个,并且在所有情况下都返回指定的确切空格数。

  • 到目前为止,我已经提出了以下正则表达式:
    /(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
    除了只返回第一个和最后一个数字(10000 和 800)而不返回其他数字的 ON ERR GOTO 之外,所有匹配的组都可以。

    我错过了什么?谢谢 :)

    最佳答案

    使用正则表达式无法获得任意数量的捕获,也无法使用 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 - 使用正则表达式提取 GOTO/GOSUB 的行号,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46151114/

    10-13 01:20