62

I am trying to use a regex for replacing text in a file (replace a full url with just protocol/domain/):

:%s/\(https\?:\/\/.*?\/\).*/\1/gc

Unfortunately .*? does not match the string, even trying to escape the ? quantifier? How should non-greedy quantifier be escaped in vim?

2

3 Answers 3

88

Vim's regex has special syntax for non-greedy versions of operators (it's kind of annoying, but you just have to memorize them): http://vimregex.com/#Non-Greedy

The non-greedy version of * is \{-}. So, simply replace .* with .\{-}:

:%s/\(https\?:\/\/.\{-}\/\).*/\1/gc
4
  • 9
    I can see now why some people prefer emacs.
    – tejasvi88
    Feb 6, 2021 at 4:59
  • 2
    What's the non-greedy version of \+ Mar 27, 2021 at 12:33
  • This is really inexcusable. What ever happened to perldo? Oct 4, 2021 at 17:30
  • @theonlygusti \{-n,} is the non-greedy version of \+
    – yaccob
    Aug 25, 2022 at 14:23
19

I prefer always breaking the problem into two steps:

/\v(https?):\/\/(.{-})\/.*        <-- Search
:%s,,Protocol:\1 - Domain:\2,g    <-- Substitution

Using very magic "\v" to avoid many backslashes, referencing the last search in substitution and changing substitution delimiter. All these changes make the code more readable.

enter image description here

3

You can also use the [^\]+/. to prevent greediness. [^/] means "match anything expect /, and + repeats that one or more times..

:%s!\v^(https?)\://([^/]+)/.*$!Protocol:\1 \t Domain:\2!g

If I have / in the regex, I will use ! as a separator so that I don't have to escape /.

Example

Let's suppose you have the following urls:

http://academy.mises.org/courses/econgd/
http://academy.mises.org/moodle/course/view.php?id=172
http://acmsel.safaribooksonline.com/book/-/9781449358204?bookview=overview
http://acmsel.safaribooksonline.com/home
http://acordes.lacuerda.net/bebo__cigala/lagrimas_negras-2.shtml
http://acordes.lacuerda.net/jose_antonio_labordeta/albada.shtml
http://anarchitext.wordpress.com/category/new-middle-east/
https://courses.edx.org/courses/course-v1%3ADelftX%2BFP101x%2B3T2015/wiki/DelftX.FP101x.3T2015/resources-and-links/
https://cseweb.ucsd.edu/classes/wi11/cse230/lectures.html
https://developer.mozilla.org/en-US/docs/CSS
https://developers.google.com/edu/python
https://developers.google.com/structured-data/testing-tool/

Applying the substitution you would get that :

Protocol:http    Domain:academy.mises.org
Protocol:http    Domain:academy.mises.org
Protocol:http    Domain:acmsel.safaribooksonline.com
Protocol:http    Domain:acmsel.safaribooksonline.com
Protocol:http    Domain:acordes.lacuerda.net
Protocol:http    Domain:acordes.lacuerda.net
Protocol:http    Domain:anarchitext.wordpress.com
Protocol:https   Domain:courses.edx.org
Protocol:https   Domain:cseweb.ucsd.edu
Protocol:https   Domain:developer.mozilla.org
Protocol:https   Domain:developers.google.com
Protocol:https   Domain:developers.google.com
2
  • 3
    I think + doesn't work it has to be \+ Mar 27, 2021 at 12:33
  • 1
    @theonlygusti note that the pattern uses \v, so that + is correct, among other changes.
    – D. Ben Knoble
    Nov 19, 2021 at 12:54

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.