如何使用正则表达式来搜索多变量模式并正确实现搜索方法来查找每次迭代?

How can you use Regex to search for a multivariable pattern and correctly implement a search method to find every iteration?

提问人:Charles Crawford 提问时间:3/14/2023 最后编辑:Peter SeligerCharles Crawford 更新时间:3/15/2023 访问量:65

问:

我需要帮助搜索包含数千行特定文本系列的文本文件。在这一点上,正则表达式就在我之上,尽管我现在已经阅读了许多关于如何实现它们的网页。这让我摸不着头脑,我知道这是可能的,这是一个我似乎无法解决的难题。我目前正在使用 Javascript 沙箱,但如果其他地方有更好的语言工具,那绝对没有必要。

具体来说,我正在寻找一个我玩过的特定国际象棋游戏,它涉及 5 个连续的白棋骑士动作。我看到的问题是文本的格式是:

"... ##.N*** X*** ##.N*** X*** ......”

哪里:

  1. 省略号代表 5 个连续骑士动作之前或之后的动作 - 当我输入这个问题时意识到这对解决方案并不重要,但确实有助于上下文
  2. “N”代表白棋的骑士 - 文字字符串,区分大小写
  3. “##.”表示移动数字,几乎可以是任何数字(不带前 0 的个位数),后跟句点。
  4. “X”代表黑棋在白骑士移动后可以移动的棋子(即。N、R、B、K、Q,或者如果它是棋子,什么都没有)
  5. “***”表示棋子移动到的正方形,如果涉及捕获,则表示“X”,如果涉及捕获,则表示字母 (a-g) 后跟数字 (1-8)。
  6. 每组字符之间都有空格

同样,这只是一个谜题,但在我缺乏经验的情况下,我从根本上或机械上错过了一些东西。

我已经研究了应该使这变得容易的典型通配符实现,但是我尝试组合十几个不同的正则表达式来拆分文本的时间非常短,并且搜索函数本身在匹配的第一个返回时停止,这可能不是我正在搜索的游戏,所以我需要继续搜索整个文档并返回所有实例。

这个问题的附加部分,我只需要返回这场比赛的位置或线路即可在文档中找到它并拉出关联的游戏。粗略的搜索给了我,然后只是将位置返回到控制台似乎很容易,但可能效率低下。 有没有更好的方法?let position = search.text(regex);

对不起,我没有我所有正则表达式尝试的完整列表。

https://regexkit.com/javascript-regex 使用以下内容可以让我匹配,但没有组。我不确定我的错误在哪里。

^.*[0-9]\d\.\sNx?[a-h].*[1-8]\s.*[A-Z]x?.*[a-h].*[1-8]\s.*[0-9]\d\.\sNx?.*[a-h].*[1-8]\s.*[A-Z]x?.*[a-h].*[1-8]\s$

像上面这样的东西应该可以作为原型来找到两个连续的骑士动作。进一步推断是一个复制粘贴的问题,但即使是这样我也逃避了。

如果需要示例文本来测试正则表达式解决方案,请参阅下文。下面的第一场比赛,有四个连续的骑士动作,第二场比赛有两个,这应该有助于解决问题。

[活动“现场国际象棋”] [网站“Chess.com”] [日期“2023.02.17”] [圆形“-”] [白色“-”] [黑色“-”] [结果“1-0”] [WhiteElo“925”] [布莱克埃洛“939”] [时间控制“180+2”] [结束时间“太平洋标准时间 17:39:13”] [终止“-将死获胜”]

E4 E5 2.Nc3 d6 3.Bc4 h6 4.d3 Nc6 5.f4 Qe7 6.NF3 Be6 7.f5 Bxc4 8.DXC4型 O-O-O 9.b3 NF6 10.O-O g5 11.FXG6 FXG6 12.Nh4 g5 13.Ng6 Qg7 14.Nxh8 Qxh8 15. Nd5 Nxd5 16.exd5 Nd4 17.c3 Nxb3 18.AXB3 A6 19.b4 Be7 20.Qg4+ Kb8 21.B5型 AXB5 22.CXB5 B6 23.Qa4 Kc8 24.Qa8+ Kd7 25.Qc6+ Kc8 26.拉8# 1-0

[活动“现场国际象棋”] [网站“Chess.com”] [日期“2023.02.17”] [圆形“-”] [白色“-”] [黑色“-”] [结果“1-0”] [WhiteElo “914”] [BlackElo“841”] [时间控制“180+2”] [结束时间“太平洋标准时间 19:06:57”] [终止“-辞职获胜”]

E4 E5 2.Nc3 Nc6 3.Bc4 NF6 4.d3 Bc5 5.Na4 Bb4+ 6.c3 Be7 7.F4 B5 8.Bxb5型 答6 9.Bc4 O-O 10.F5 D5 11.exd5 Nxd5 12.NF3 Bxf5 13.O-O Bc5+ 14.Nxc5 NF4 15. Nxe5 Nxe5 16.Rxf4 Bg4 17.Rxg4 Nxg4 18.Qxg4 Re8 19.BH6 G6 1-0

感谢大家的时间和耐心。

编辑:游戏文本的复制/粘贴错误,缺少“15”。添加了“N”作为可能的对手动作,以保持清晰/完整。

javascript 式字符串 匹配 则表达式组

评论

2赞 Ouroborus 3/14/2023
正则表达式几乎从来都不是复杂匹配的好选择。
0赞 Charles Crawford 3/14/2023
我担心这太复杂了,但只是将其归因于我缺乏经验。那我应该用什么方法呢?正则表达式似乎是唯一的出路。
0赞 Peter Seliger 3/14/2023
@CharlesCrawford......像这样的东西?../(?:\s+\d+\.\s+Nx?[a-h][1-8]\s+[RBKQN]?x?[啊-h][1-8])+/克 ...或者对于至少两个连续移动的最小序列,类似?../(?:\s+\d+\.\s+Nx?[a-h][1-8]\s+[RBKQN]?x?[啊-h][1-8]){2,}/g ...顺便说一句......第一个示例游戏日志错过了移动数字 15。
0赞 Peter Seliger 3/14/2023
@Ouroborus......“正则表达式几乎从来都不是复杂匹配的好选择。”...我个人认为正则表达式实际上是唯一允许立即表达 OP 明确要求的工具。
2赞 Charles Crawford 3/15/2023
@Ouroborus 就其价值而言,我完全同意您对未来使用的评估。这是一个非常小众的用途。把你和彼得给我的信息都当作金子,这个问题是值得的,因为我现在有一个学习的跳跃平台。Peters 的第二个正则表达式示例是 100% 适用于我在这里需要的东西。非常感谢你们俩抽出时间。我有很多阅读要做。

答:

0赞 Peter Seliger 3/15/2023 #1

OP 的串行伪占位符模式......表示为 (a) 分组的正则表达式模式转换为以下正则表达式伪代码......##. N*** X*** ##. N*** X***

  • (?: pattern )+...对于至少一个(或多个)匹配的非捕获组。
  • (?: pattern ){2,}...对于至少两个(或更多)匹配的非捕获组的序列。

的最小占位符代码与 OP 的描述/要求一起直接转换为最后两个表达式中的任何一个......##. N*** X***

    '   ##.    N*   *    *        X    *   *    *'
     ^  ^^^  ^ ^^   ^    ^   ^    ^    ^   ^    ^
/(?:\s+\d+\.\s+Nx?[a-h][1-8]\s+[RBKQN]?x?[a-h][1-8])+/g
/(?:\s+\d+\.\s+Nx?[a-h][1-8]\s+[RBKQN]?x?[a-h][1-8]){2,}/g

...它的每个描述都可以在模式的 test/playground 页面上找到......

如果 OP 想要匹配任何黑夜移动的发生,用例如下......

console.log(
`[Event "Live Chess"] [Site "Chess.com"] [Date "2023.02.17"] [Round "-"] [White "-"] [Black "-"] [Result "1-0"] [WhiteElo "925"] [BlackElo "939"] [TimeControl "180+2"] [EndTime "17:39:13 PST"] [Termination "- won by checkmate"]

e4 e5 2. Nc3 d6 3. Bc4 h6 4. d3 Nc6 5. f4 Qe7 6. Nf3 Be6 7. f5 Bxc4 8. dxc4 O-O-O 9. b3 Nf6 10. O-O g5 11. fxg6 fxg6 12. Nh4 g5 13. Ng6 Qg7 14. Nxh8 Qxh8 15. Nd5 Nxd5 16. exd5 Nd4 17. c3 Nxb3 18. axb3 a6 19. b4 Be7 20. Qg4+ Kb8 21. b5 axb5 22. cxb5 b6 23. Qa4 Kc8 24. Qa8+ Kd7 25. Qc6+ Kc8 26. Ra8# 1-0

[Event "Live Chess"] [Site "Chess.com"] [Date "2023.02.17"] [Round "-"] [White "-"] [Black "-"] [Result "1-0"] [WhiteElo "914"] [BlackElo "841"] [TimeControl "180+2"] [EndTime "19:06:57 PST"] [Termination "- won by resignation"]

e4 e5 2. Nc3 Nc6 3. Bc4 Nf6 4. d3 Bc5 5. Na4 Bb4+ 6. c3 Be7 7. f4 b5 8. Bxb5 a6 9. Bc4 O-O 10. f5 d5 11. exd5 Nxd5 12. Nf3 Bxf5 13. O-O Bc5+ 14. Nxc5 Nf4 15. Nxe5 Nxe5 16. Rxf4 Bg4 17. Rxg4 Nxg4 18. Qxg4 Re8 19. Bh6 g6 1-0`

 .match(/(?:\s+\d+\.\s+Nx?[a-h][1-8]\s+[RBKQN]?x?[a-h][1-8])+/g)
 .map(result => result.trim())
)

如果 OP 需要任何匹配的黑夜移动的指数,上述用例将更改为......

console.log([
...`[Event "Live Chess"] [Site "Chess.com"] [Date "2023.02.17"] [Round "-"] [White "-"] [Black "-"] [Result "1-0"] [WhiteElo "925"] [BlackElo "939"] [TimeControl "180+2"] [EndTime "17:39:13 PST"] [Termination "- won by checkmate"]

e4 e5 2. Nc3 d6 3. Bc4 h6 4. d3 Nc6 5. f4 Qe7 6. Nf3 Be6 7. f5 Bxc4 8. dxc4 O-O-O 9. b3 Nf6 10. O-O g5 11. fxg6 fxg6 12. Nh4 g5 13. Ng6 Qg7 14. Nxh8 Qxh8 15. Nd5 Nxd5 16. exd5 Nd4 17. c3 Nxb3 18. axb3 a6 19. b4 Be7 20. Qg4+ Kb8 21. b5 axb5 22. cxb5 b6 23. Qa4 Kc8 24. Qa8+ Kd7 25. Qc6+ Kc8 26. Ra8# 1-0

[Event "Live Chess"] [Site "Chess.com"] [Date "2023.02.17"] [Round "-"] [White "-"] [Black "-"] [Result "1-0"] [WhiteElo "914"] [BlackElo "841"] [TimeControl "180+2"] [EndTime "19:06:57 PST"] [Termination "- won by resignation"]

e4 e5 2. Nc3 Nc6 3. Bc4 Nf6 4. d3 Bc5 5. Na4 Bb4+ 6. c3 Be7 7. f4 b5 8. Bxb5 a6 9. Bc4 O-O 10. f5 d5 11. exd5 Nxd5 12. Nf3 Bxf5 13. O-O Bc5+ 14. Nxc5 Nf4 15. Nxe5 Nxe5 16. Rxf4 Bg4 17. Rxg4 Nxg4 18. Qxg4 Re8 19. Bh6 g6 1-0`

 .matchAll(/(?:\s+\d+\.\s+Nx?[a-h][1-8]\s+[RBKQN]?x?[a-h][1-8])+/g)]
   .map(result => result.index)
);

如果 OP 只想知道连续黑夜移动的匹配/指数,上述两个用例都更改为......

const regXConsecutiveBlackNightMoves =
  /(?:\s+\d+\.\s+Nx?[a-h][1-8]\s+[RBKQN]?x?[a-h][1-8]){2,}/g;

const sampleText =
`[Event "Live Chess"] [Site "Chess.com"] [Date "2023.02.17"] [Round "-"] [White "-"] [Black "-"] [Result "1-0"] [WhiteElo "925"] [BlackElo "939"] [TimeControl "180+2"] [EndTime "17:39:13 PST"] [Termination "- won by checkmate"]

e4 e5 2. Nc3 d6 3. Bc4 h6 4. d3 Nc6 5. f4 Qe7 6. Nf3 Be6 7. f5 Bxc4 8. dxc4 O-O-O 9. b3 Nf6 10. O-O g5 11. fxg6 fxg6 12. Nh4 g5 13. Ng6 Qg7 14. Nxh8 Qxh8 15. Nd5 Nxd5 16. exd5 Nd4 17. c3 Nxb3 18. axb3 a6 19. b4 Be7 20. Qg4+ Kb8 21. b5 axb5 22. cxb5 b6 23. Qa4 Kc8 24. Qa8+ Kd7 25. Qc6+ Kc8 26. Ra8# 1-0

[Event "Live Chess"] [Site "Chess.com"] [Date "2023.02.17"] [Round "-"] [White "-"] [Black "-"] [Result "1-0"] [WhiteElo "914"] [BlackElo "841"] [TimeControl "180+2"] [EndTime "19:06:57 PST"] [Termination "- won by resignation"]

e4 e5 2. Nc3 Nc6 3. Bc4 Nf6 4. d3 Bc5 5. Na4 Bb4+ 6. c3 Be7 7. f4 b5 8. Bxb5 a6 9. Bc4 O-O 10. f5 d5 11. exd5 Nxd5 12. Nf3 Bxf5 13. O-O Bc5+ 14. Nxc5 Nf4 15. Nxe5 Nxe5 16. Rxf4 Bg4 17. Rxg4 Nxg4 18. Qxg4 Re8 19. Bh6 g6 1-0`;

console.log(
  sampleText
    .match(regXConsecutiveBlackNightMoves)
    .map(result => result.trim())
)
console.log([
  ...sampleText
    .matchAll(regXConsecutiveBlackNightMoves)
  ]
  .map(result => result.index)
);

基本模式还有两个额外的变体,对于多行搜索,它们将完全部分匹配游戏,同时捕获第一个连续出现的黑夜移动。

评论

1赞 Charles Crawford 3/16/2023
谢谢你,我昨晚实际上在做一些类似的事情来结束这个问题。然而,我不会那么完整或措辞强硬。非常感谢您抽出宝贵时间。