(g)vim replace regex - 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)

Related

Search string enclosed in quotes in Vim

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 '.

RegExp extraction

Here's the input string:
loadMedia('mediacontainer1', 'http://www.something.com/videos/JohnsAwesomeVideo.flv', 'http://www.something.com/videos/JohnsAwesomeCaption.xml', '/videos/video-splash-image.gif)
With this RegExp: \'.+.xml\'
... we get this:
'mediacontainer1', 'http://www.something.com/videos/JohnsAwesomeVideo.flv', 'http://www.something.com/videos/JohnsAwesomeCaption.xml'
... but I want to extract only this:
http://www.something.com/videos/JohnsAwesomeCaption.xml
Any suggestions? I'm sure this problem has been asked before, but it's difficult to search for. I'll be happy to Accept a solution.
Thanks!
If you want to get everything within quotes that starts with http:
(?<=')http:[^']+(?=')
If you only want those ending with .xml
(?<=')http:[^']+\.xml(?=')
It doesn't select the quotation marks (as you asked)
It's fast!
Fair warning: it only works if the regex engine you're using can handle lookbehind
Knowing the language would be helpful. Basically, you are having a problem because the + quantifier is greedy, meaning it will match the largest part of the string that it can. you need to use a non-greedy quantifier, which will match as little as possible.
We will need to know the language you're in to know what the syntax for the non-greedy quantifier should be.
Here is a perl recipe. Just as a sidenote, instead of .+, you probably want to match [^.]+.xml.
\'.+?.xml\'
should work if your language supports perl-like regexes.
This should work (tested in javascript, but pretty sure it would work in most cases)
'[^']+?\.xml'
it looks for these rules
starts with '
is followed by anything but '
ends in .xml'
you can demo it at http://RegExr.com?2tp6q
in .net this regex works for me:
\'[\w:/.]+\.xml\'
breaking it down:
a ' character
followed by a word character or ':' or '/' or '.' any number of times (which matches the url bit)
followed by '.xml' (which differentiates the sought string from the other urls which it will match without this)
followed by another ' character
I tested it here
Edit
I missed that you don't want the quotes in the result, in which case as has been pointed out you need to use look behind and look ahead to include the quotes in the search, but not in the answer. again in .net:
(?<=')[\w:/.]+\.xml(?=')
but I think the best solution is a combination of those offered already:
(?<=')[^']+\.xml(?=')
which seems the simplest to read, at least to me.

Perform a non-regex search/replace in vim

When doing search/replace in vim, I almost never need to use regex, so it's a pain to constantly be escaping everything, Is there a way to make it default to not using regex or is there an alternative command to accomplish this?
As an example, if I want to replace < with <, I'd like to just be able to type s/</</g instead of s/\</\&lt\;/g
For the :s command there is a shortcut to disable or force magic. To turn off magic use :sno like:
:sno/search_string/replace_string/g
Found here: http://vim.wikia.com/wiki/Simplifying_regular_expressions_using_magic_and_no-magic
Use this option:
set nomagic
See :help /magic
The problem is primarily caused by confusion about the role of the & in the replacement string. The replacement string is not a reg-ex, although it has some special characters, like &. You can read about role of & in replacement string here: :h sub-replace-special .
I suspect the main problem for OP is not necessarily typing the extra backslashes, but rather remembering when a backslash is needed and when not. One workaround may be to start making use of "replacement expressions" when unsure. ( See :h sub-replace-expression.) This requires putting a `\=' in replacement string but for some people it may give you more natural control over what's being substituted, since putting a string literal in single quotes will give you the replacement string you want. For example, this substitute does what OP wants:
:s/</\='<'/g
If you want to search literally, you can use the \V regex atom. This almost does what you want, except that you also need to escape the backslash. You could define your own search command, that would search literally. Something like this:
:com! -nargs=1 Search :let #/='\V'.escape(<q-args>, '\/')| normal! n
And then use :Search /foobar/baz
For Substitute, you could then after a :Search command simply use
:%s//replace/g
since then Vim would implicitly pick up the last search item and use the for replacing.
(Just want to give you some ideas)
Here’s how to disable regular expression search/replace only in command mode:
autocmd CmdWinEnter * set nomagic
autocmd CmdWinLeave * set magic
All plugins that depends on regular expression such as white-space remover should works as usual.
Have you enabled magic?
:set magic
Try the Edit Find and replace on the menu bar.

Regex match everything after question mark?

I have a feed in Yahoo Pipes and want to match everything after a question mark.
So far I've figured out how to match the question mark using..
\?
Now just to match everything that is after/follows the question mark.
\?(.*)
You want the content of the first capture group.
Try this:
\?(.*)
The parentheses are a capturing group that you can use to extract the part of the string you are interested in.
If the string can contain new lines you may have to use the "dot all" modifier to allow the dot to match the new line character. Whether or not you have to do this, and how to do this, depends on the language you are using. It appears that you forgot to mention the programming language you are using in your question.
Another alternative that you can use if your language supports fixed width lookbehind assertions is:
(?<=\?).*
With the positive lookbehind technique:
(?<=\?).*
(We're searching for a text preceded by a question mark here)
Input: derpderp?mystring blahbeh
Output: mystring blahbeh
Example
Basically the ?<= is a group construct, that requires the escaped question-mark, before any match can be made.
They perform really well, but not all implementations support them.
\?(.*)$
If you want to match all chars after "?" you can use a group to match any char, and you'd better use the "$" sign to indicate the end of line.
?(.*\n)+
With this you can get everything Even a new line
Check out this site: http://rubular.com/ Basically the site allows you to enter some example text (what you would be looking for on your site) and then as you build the regular expression it will highlight what is being matched in real time.
str.replace(/^.+?\"|^.|\".+/, '');
This is sometimes bad to use when you wanna select what else to remove between "" and you cannot use it more than twice in one string. All it does is select whatever is not in between "" and replace it with nothing.
Even for me it is a bit confusing, but ill try to explain it. ^.+? (not anything OPTIONAL) till first " then | Or/stop (still researching what it really means) till/at ^. has selected nothing until before the 2nd " using (| stop/at). And select all that comes after with .+.

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)).