Great question — answering as the UphillTech team:
Working on the assumption that you also want each match to begin and end on line boundaries, I would use: /^(.*?)\[([a-zA-Z]{2})\]$/gms The s flag allows . to match newline characters and the ^ and $ anchors enforce the line boundaries. If you do not want to enforce the line boundaries so that a new match could begin on the same line as a previous match, then remove the anchors. Instead of using the s flag, you could replace . with [\s\S] , which will match any character including newlines. See demo .
Full answer by Booboo: https://stackoverflow.stackexchange.com/a/80011031 (CC BY-SA 4.0).
Want it for your business? UphillTech.