Can we write functions/subroutines in csh or vim?
Basically, my question is how to slash the backslashes inside a string automatically which we use for search in vim.
Lets say:
Contents of file file_a is:
abcd
a/b/c/d
Now, if I search 'abcd' inside vim with "/abcd" in command mode, it will match abcd(first line).
And If I search for 'a/b/c/d', it will not match whole of 'a/b/c/d'. It will match only 'a' from 'a/b/c/d'.
To match whole of 'a/b/c/d', I would need to search for a\/b\/c\/d. Slashing backslashes is a pain every time you want to search for strings having backslashes inside it. :)
Have anyone of you solved this earlier?
In Vim:
You can search backwards, where the separator is ? instead of /, so / does not need to be escaped: ?a/b/c/d; to move to the next match downwards, use N.
Or you can set the search pattern using :let #/="a/b/c/d" (this will not move the cursor), then use n to go the next match.
You can also define your own command:
function! FindSlashed(arg)
let #/=a:arg
norm n
endfunction
command! -nargs=1 S call FindSlashed(<q-args>)
which you can use like this:
:S a/b/c/d
EDIT: let, not set.
This is not about searching but about replacing. I thought you might find this helpful as you're writing functions
You can use alternate delimiters for replace command. ie, rather than using /, you can use something like #
:s#a/b/c/d#this text will replace#
The above command will replace a/b/c/d with this text will replace
Related
I have file containing abc(de+fgh(2a+2b))+xyz(). i want to write regexp(preferably vim) to get a pattern like de+fgh(2a+2b) + xyz() .
I tried in gvim regexp But while matching parenthesis, if i use greedy option it will match abc(de+fgh(2a+2b))+xyz() and for non-greedy option it will matching with abc(de+fgh(2a+2b')')+xyz() , how to match with abc(de+fgh(2a+2b)')'+xyz().
Regards
keerthan
I won't do it with regex, assume that your cursor is at BOL, just do:
%di(v0p
you will get desired output.
Translating it into english, take the stuff between first (..) group and concatenate it with whatever after the first (...) group.
You can use :normal cmd or macro to apply the operations on multiple lines.
Watch out! regex cannot handle counting arbitrary numbers of brackets. If you want to do this generally, you might need to write a parser.
That said, if you only need this to work for a specific case:
http://regexr.com/3fne0
in vim this is:
%s/[^()]*(\([^()]*([^()]*)\))\(.*\)/\1\2/g
I have a bunch of files in a directory that were produced with rather unfortunate names. I want to change two of the characters in the name.
For example I have:
>ch:sdsn-sdfs.txt
and I want to remove the ">" and change the ":" to a "_".
Resulting in
ch_sdsn-sdfs.txt
I tried to just say mv \\>ch\:* ch_* but that didn't work.
Is there a simple solution to this?
For command line script to rename, this stackoverflow question has good answers.
For Mac, In GUI, Finder comes with bulk rename capabilities. If source list of files has some pattern to find & replace, it comes very handy.
Select all the files that need to be replaced, right click and select rename
On rename, enter find and replace string
Other options in rename, to sequence the file names:
To prefix or suffix text:
First, I should say that the easiest way to do this is to use the
prename or rename commands.
Homebrew package rename, MacPorts package renameutils :
rename s/0000/000/ F0000*
That's a lot more understandable than the equivalent sed command.
But as for understanding the sed command, the sed manpage is helpful. If
you run man sed and search for & (using the / command to search),
you'll find it's a special character in s/foo/bar/ replacements.
s/regexp/replacement/
Attempt to match regexp against the pattern space. If successâ
ful, replace that portion matched with replacement. The
replacement may contain the special character & to refer to that
portion of the pattern space which matched, and the special
escapes \1 through \9 to refer to the corresponding matching
sub-expressions in the regexp.
Therefore, \(.\) matches the first character, which can be referenced by \1.
Then . matches the next character, which is always 0.
Then \(.*\) matches the rest of the filename, which can be referenced by \2.
The replacement string puts it all together using & (the original
filename) and \1\2 which is every part of the filename except the 2nd
character, which was a 0.
This is a pretty cryptic way to do this, IMHO. If for
some reason the rename command was not available and you wanted to use
sed to do the rename (or perhaps you were doing something too complex
for rename?), being more explicit in your regex would make it much
more readable. Perhaps something like:
ls F00001-0708-*|sed 's/F0000\(.*\)/mv & F000\1/' | sh
Being able to see what's actually changing in the
s/search/replacement/ makes it much more readable. Also it won't keep
sucking characters out of your filename if you accidentally run it
twice or something.
I have a file contains a lot of functions, each function like
=======
CREATE PROCEDURE [fName]
code...
code...
END
GO
=======
I want to get every function pattern, and the expression I used is
^(CREATE PROCEDURE).*(\r\n.*)+\r\nGO
The result is wrong. Can somebady help! Thanks for answer
Using sed:
sed -n '/CREATE PROCEDURE/,/^END$/{H};/^GO$/{s/.*//;x;p;}' input
Try something more like:
(?<=^|\n)(CREATE PROCEDURE [\s\S]+?)(?=\r\nGO|$)
This will match every instance of CREATE PROCEDURE that starts a new line and the text that follows it, up to but not including the next GO directive, or the end of the file, whichever comes first.
In [\s\S]+?, the question mark makes this a non-greedy match, which is how we stop at the next GO instead of the last GO. [\s\S] is equivalent to [.\n], i.e., it matches any character.
I've assumed .NET-style regular expressions, since you didn't specify.
instead of using "." and \r\n try using [\s\S] it matches anything that is a whitespace OR isn't a whitespace including newlines.
CREATE PROCEDURE[\s\S]*GO
This may need some regex flags to be set
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.
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.