64

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

93

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
7
  • 9
    I can see now why some people prefer emacs.
    – tejasvi88
    Commented Feb 6, 2021 at 4:59
  • 2
    What's the non-greedy version of \+
    – minseong
    Commented Mar 27, 2021 at 12:33
  • This is really inexcusable. What ever happened to perldo? Commented Oct 4, 2021 at 17:30
  • 1
    @theonlygusti \{-n,} is the non-greedy version of \+
    – yaccob
    Commented Aug 25, 2022 at 14:23
  • The non-greedy version on \+ is \{-1,} Commented Sep 22, 2023 at 7:16
22

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

1
  • 1
    I like the very magic switch and the converse, the no magic switch (\V). If you know you're ramping up for a complex regex or one with edge cases like this prefixing with very magic simplifies, but on the other hand if you know you're mostly seeking for a simple literal match using \V can also save keystrokes.
    – NeilG
    Commented Sep 29, 2023 at 2:39
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 \+
    – minseong
    Commented Mar 27, 2021 at 12:33
  • 1
    @theonlygusti note that the pattern uses \v, so that + is correct, among other changes.
    – D. Ben Knoble
    Commented Nov 19, 2021 at 12:54

Your Answer

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

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