Getting first number from string

The following function fails to return "16":

(string-to-number "bm16")

It seems to get tripped up if the first characters of a string aren't numbers. Is there a way to construct an elisp function which takes a string of text and returns the number it contains (it doesn't have to handle decimals)?

• There is no function named first-number-from-string in my emacs: how is it defined? where did you get it from? Mar 17 '21 at 5:00
• NickD: My mistake. I meant string-to-number. Mar 17 '21 at 5:22
• What should happen for the string "abcdef" which contains no digits? And do you want the result to be a number or its string representation? Mar 17 '21 at 5:27

A possible implementation: find the first digit, get the substring of the original string that starts at that first digit and then call string-to-number on the result:

(defun first-number-of-string (s)
(string-to-number (substring s (string-match-p "[0-9]" s))))

(first-number-of-string "bm16" -> 16
(first-number-of-string "abc123def456" -> 123
(first-number-of-string "abc123") -> 123
(first-number-of-string "123def") -> 123
(first-number-of-string "123") -> 123
(first-number-of-string "abcdef") -> 0

That's assuming that the answers to the questions in my comment are that you indeed want a number, not its string representation, and in the case where there is no number in the string, having the function return 0 is acceptable.

An alternative using cl functions:

(defun first-number-in-string(s)
(string-to-number
(seq-take-while
#'cl-digit-char-p
(seq-drop-while
(lambda(x)(not (cl-digit-char-p x)))
s))))

(mapcar #'first-number-in-string
'( "bm16" "abc123def456" "abc123" "123def" "123" "abcdef"))
=>     (16 123 123 123 123 0)

The same algorithm splitted for clarity::

(defun collect-first (pred coll)
(seq-take-while pred
(seq-drop-while (lambda (x) (not(funcall pred x)))
coll)))

(defun first-number-in-string(s)
(string-to-number
(collect-first #'cl-digit-char-p  s)))