Search string enclosed in quotes in Vim - regex

In vim I need to search all strings in quotes e.g. 'foo'
Does one see the problem in this regex? E486: Pattern not found \'([^']*)'
:\/'([^']*)'
Regex Tester

First problem is that your use of find is a bit confusing. If you want
to just find, use /. The colon is not necessary (which indicates
command mode). If you're using the find as a range (basically the same
thing, / is just an empty command with a range) you can use the colon,
but either way escaping the first slash is not necessary.
The other main problem is that parenthesis by default need to be escaped
if you meant a capturing group. All of this is dependant on your
'magic' option reading the help for the /magic topic (you can do a
:h magic) is highly recommended. With "vanilla" Vim settings, the
regex you need looks live this:
/'\([^']*\)'
With very magic enable (by using the \v atom) this can be simplified
to your original design:
/\v'([^']*)'

Alternatively you can use
\v'(\a+)'
this regex performs similar than yours, except when nested quotes are encountered. In the text:
The user's first 'answer'.
The regex \v'(\a+)' will capture answer while your original regex (corrected by sidyll) \v'([^']*)' will capture 's first '.

Related

In vim is it possible to use the same regex escaping rules for :substitute and search?

If I do a search (with magic) like: /\v\$[^ ]+\$ I get matches in my file, however if I substitute with the same search pattern: :%smagic/\$[^ ]+\$//, I need to escape the +.
Is it possible to make the escaping behave in the same way for magic search and magic substitute?
:smagic is like :s with 'magic' on, which is the default (and should not be changes for plugin portability, as its :help notes). The \v special atom specifies very magic, so additional atoms (like \+) do not need the preceding backslash.
There's no corresponding :s command variant, but why don't you just keep the \v in the pattern:
:%s/\v\$[^ ]+\$//
(Also, if you've previously searched for that, you can leave off the pattern completely: :%s///.)
use \v instead of magic
:%s/\v\$[^ ]+\$//

Adding "/index.html" to paths in Vim

I'm trying to append "/index.html" to some folder paths in a list like this:
path/one/
/another/index.html
other/file/index.html
path/number/two
this/is/the/third/path/
path/five
sixth/path/goes/here/
Obviously the text only needs to be added where it does not exist yet. I could achieve some good results with (vim command):
:%s/^\([^.]*\)$/\1\/index.html/
The only problem is that after running this command, some lines like the 1st, 5th and 7th in the previous example end up with duplicated slashes. That's easy to solve too, all I have to do is search for duplicates and replace with a single slashes.
But the question is:
Isn't there a better way to achieve the correct result at once?
I'm a Vim beginner, and not a regex master also. Any tips are really appreciated!
Thanks!
So very close :)
Just add an optional slash to the end of the regex:
\/\?
Then you need to change the rest of the pattern to a non-greedy match so that it ignores a trailing slash. The syntax for a non-greedy match in vim (replacing the *) is:
\{-}
So we end up with:
:%s/^\([^\.]\{-}\)\/\?$/\1\/index.html/
(Doesn't hurt to be safe and escape the period.)
Vim's regex supports the ability to match a bit of text foo if it does or doesn't precedes or follows some other text bar without matching bar, and this is exactly the sort of thing you're looking for. Here you want to match the end of line with an optional /, but only if the / isn't followed by index.html, and then replace it with /index.html. A quick look at Vim's help tells me \#<! is exactly what to use. It tells Vim that the preceding atom must be in the text but not in what's matched. With a little experimentation, I get
:%s;/\?\(index\.html\)\#<!$;/index.html;
I use ; to delimit the parts of the :s command so that I don't have to escape any / in the regex or replacement expression. In this particular situation, it's not a big deal though.
The / is optional, and we say so with \?.
We need to group index.html together because otherwise our special \#<! would only affect the l otherwise.

How to search (using regex) for a regex literal in text?

I just stumbled on a case where I had to remove quotes surrounding a specific regex pattern in a file, and the immediate conclusion I came to was to use vim's search and replace util and just escape each special character in the original and replacement patterns.
This worked (after a little tinkering), but it left me wondering if there is a better way to do these sorts of things.
The original regex (quoted): '/^\//' to be replaced with /^\//
And the search/replace pattern I used:
s/'\/\^\\\/\/'/\/\^\\\/\//g
Thanks!
You can use almost any character as the regex delimiter. This will save you from having to escape forward slashes. You can also use groups to extract the regex and avoid re-typing it. For example, try this:
:s#'\(\\^\\//\)'#\1#
I do not know if this will work for your case, because the example you listed and the regex you gave do not match up. (The regex you listed will match '/^\//', not '\^\//'. Mine will match the latter. Adjust as necessary.)
Could you avoid using regex entirely by using a nice simple string search and replace?
Please check whether this works for you - define the line number before this substitute-expression or place the cursor onto it:
:s:'\(.*\)':\1:
I used vim 7.1 for this. Of course, you can visually mark an area before (onto which this expression shall be executed (use "v" or "V" and move the cursor accordingly)).

(g)vim replace regex

I'm looking for a regex that will change sth. like this:
print "testcode $testvar \n";
in
printnlog("testcode $testvar \n");
I tried %s/print\s*(.\{-});/printnlog(\1);/g but gvim says
print\s*(.\{-});
doesn't match.
Where is my fault?
Is it ok to use '*' after '\s' because later '{-};' will stop the greed?
Thanks in advance.
In vim you have to prepend (, ) and | with backslash, so try
:%s/print\s*\(.\{-}\);/printnlog(\1);/g
MBO's answer works great, but sometimes I find it easier to use the "very magic" option \v so I don't have to escape everything; makes the regex a little more readable.
See also:
:h /\v in Vim
http://briancarper.net/blog/vim-regexes-are-awesome
While you can create capture groups (like you're doing), I think the easiest approach is to do the job in multiple steps, with very simple regexes and "flag" words. For example:
:%s/print "testcode.*/printnlog(XXX&XXX);/
:%s/XXXprint //
:%s/;XXX//
In these examples, I use "XXX" to indicate boundaries that should later be trimmed (you can use anything that doesn't appear in your code). The ampersand (&) takes the entire match string and inserts it into the replacement string.
I don't know about other people, but I can type and execute these three regexes faster than I can think through a capture group.
Is this sufficient for your needs?
%s/print\s*\("[^"]*"\)/printnlog(\1)

Regex search and replace in VI

I have a document with lots of <swf...>.....</swf> in it. I would like to remove all these. Using vi when i type
:%s/\<swf[^\/swf>]+\/swf\>//g
I was hoping this would work, but it doesn't match anything.
You can remove all those from the buffer with this command:
:%s!<swf.\{-}/swf>!!
if you also have tags that might be split on two lines, you can add the \_ modifier to make . match newlines too:
:%s!<swf\_.\{-}/swf>!!
this assuming you want to remove both the tags and what they contain, if you just want to get rid of the tags and keep the content
:%s!</\?swf.\{-}>!!
Notes:
you don't need to escape < or >
you can choose whatever pattern delimiter you wish: Vim will use the first character you put after the s in the substitute command: this takes away the need to escape forward slashes in your pattern
EDIT: extending my answer after your comment
this is exactly like /STRING/REPLACE/g I only used a ! instead of / so that I don't have to quote the backslash in the pattern (see my second point above)
I didn't add the g modifier at the end since I have :set gdefault in my .vimrc since forever (it means that by default Vim will substitute all matches in a line instead of just the first, thus reverting the meaning of /g)
\{-} is the "ungreedy" version of the * quantifier, i.e. it matches 0 or more of the preceding atom but take as few as possible -- this helps you make sure that your search pattern will extend to the first "closing tag" instead of the last.
HTH
The problem here is that the [] is a character class, so you are telling it that between the swf opening and closing tags, the letters s, w and f cannot appear anywhere, in any order.
You could try a non-greedy match instead:
\<swf.\{-}\/swf\>
Note that . does not allow newline by default.
I don't use Vim though, so I used this guide to discover the syntax. I hope it is correct.