3

I want to replace below example

line1 ![img](170319_first.png "test") 
line2 ![img](170319_second.png)
line3 ![img](/assets/170319_second.png) 

to:

line1 ![img](/assets/170319_first.png "test") 
line2 ![img](/assets/170319_second.png)
line3 ![img](/assets/170319_second.png) 

which means:

  1. Do not replace line3 case (file name start with "/assets" already)
  2. Add "/assets/" to file name for line1 case (end with a space)
  3. Add "/assets/" to file name for line2 case also (end with a ')').

I try to use below code but it doesn't work.

(setq str "
line1 ![img](170319_first.png \"test\") 
line2 ![img](170319_second.png)
line3 ![img](/assets/170319_second.png)
")
(with-temp-buffer
  (insert str)
  (goto-char (point-min))
  (setq regex1 "\\!\\[img\\](\\([^/]*?\\)\\([ \\|)]\\)")
  (while (re-search-forward regex1 nil t)
    (setq regex2 (format "![img](/assets/%s" (match-string 1)))
    (replace-match regex2 nil t))
  (print (buffer-string))
  )

But the result not correct:

line1 ![img](/assets/170319_first.png\"test\") 
line2 ![img](/assets/170319_second.png
line3 ![img](/assets/170319_second.png)

Obviously, the ' ' and ')' has been replaced also. but I didn't include it in the match group.

1
  • regex2 isn't a regular expression (or certainly isn't being used as one), so that's unintuitive naming.
    – phils
    Mar 20, 2017 at 9:57

3 Answers 3

1

You want to replace SUBEXP (group) 1 only, so you should pass that argument to replace-match and then reduce the replacement string to only what is needed for that group.

I would also suggest not passing LITERAL as you can then simply use a back-reference "\\1" in the replacement string to substitute the original text matched by group 1, which eliminates the need to separately construct a replacement string using (match-string 1).

That leaves us with just:

(while (re-search-forward regex1 nil t)
  (replace-match "/assets/\\1" nil nil nil 1))
3

Since the condition of 2 and 3 can be simplified to: the character after "![img](" not be '/', below code works for this case:

(setq str "
line1 ![img](170319_first.png \"test\") 
line2 ![img](170319_second.png)
line3 ![img](/assets/170319_second.png)
")
(setq regex1 "\\!\\[img\\](\\([^/]\\)")
(setq str (replace-regexp-in-string regex1 "/assets/\\1" str nil nil 1))
(print str)

Output:

line1 ![img](/assets/170319_first.png \"test\") 
line2 ![img](/assets/170319_second.png)
line3 ![img](/assets/170319_second.png)
0
(let (
      (str-sample "
line1 ![img](170319_first.png \"test\") 
line2 ![img](170319_second.png)
line3 ![img](/assets/170319_second.png)
")
      )
  (with-temp-buffer
    (insert str-sample)
    ;; just trash
    (insert "foobar\n")
    (insert "line4 ![img](/s/170319_second.png)")
    (insert "\nDone ...\n")
    ;; well
    (goto-char (point-min))
    (while (re-search-forward "\\(.*\\)\\((\\)\\([0-9]+.*$\\)" nil t)
      (replace-match "\\1\\2/assets/\\3")
      )
    (print (buffer-string))
    )
'ok
)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.