2
votes

Is there any way to extract regular expression's group in Emacs Lisp?

For example, how can I get "std" and "1" from "std1" using regex

^\(std\|bcp\|fyi\)\([0-9]+\)$

like JavaScript

/^(std|bcp|fyi)([0-9]+)$/.exec("std1")[1]  //= std
/^(std|bcp|fyi)([0-9]+)$/.exec("std1")[2]  //= 1

http://www.gnu.org/software/emacs/manual/html_node/elisp/Regexp-Functions.html#Regexp-Functions I read this page but couldn't grasp how to achive this.

2

2 Answers

4
votes

To add to the other answer, you might want to memorize the whole (when (string-match ...) (do-something-with (match-string ...))) pattern as an idiom. Example:

(let ((str "std1")
      (reg (rx bos
               (group (or "std" "bcp" "fyi"))
               (group (+ digit))
               eos)))
  (when (string-match reg str)
    (list :1 (match-string 1 str)
          :2 (match-string 2 str))))

⇒ (:1 "std" :2 "1")

Also, s-match from the s.el library collects submatches into a list:

(require 's)
(let ((str "std1")
      (reg (rx bos
               (group (or "std" "bcp" "fyi"))
               (group (+ digit))
               eos)))
  (s-match reg str))

⇒ ("std1" "std" "1")

Then you can access elements like this:

(require 's)
(require 'dash)

(let ((str "std1")
      (reg (rx bos
               (group (or "std" "bcp" "fyi"))
               (group (+ digit))
               eos)))
  (--when-let (s-match reg str)
    (list :1 (elt it 1)
          :2 (elt it 2))))

⇒ (:1 "std" :2 "1")

In all three snippets, the return value is nil if match fails.

2
votes

Use string-match and match-string:

*** Welcome to IELM ***  Type (describe-mode) for help.
ELISP> (string-match "^\\(std\\|bcp\\|fyi\\)\\([0-9]+\\)$" "std1")
0
ELISP> (match-string 1 "std1")
"std"
ELISP> (match-string 2 "std1")
"1"

Note that you have to pass the original string to match-string - it saves the offsets in the "match data" but not the original string.