Putting "\n" in my .c or .cpp file using vim - vim

I'm using vim to make my programs in c/c++ and I would like to know how can I put "\n" (which represents a newline) in my code or use "%" using :%s.
For instance, sometimes I forget to put "%" in front of "d" or "f" in many lines or forget to put "\n" in some printf() calls.
printf("This is my d code.", x);
But the following command does not work, it puts a space in place of "\n"!
:%s/\<code.\>/code.\n/gc
or
:%s/\<d\>/%d/gc
How can I do what I want?

The :help s/\n has the answer:
\n insert a <NL> (<NUL> in the file)
(does NOT break the line) *s/\n*
You'll also find the solution there: to insert a literal backslash, escape it \\ by doubling; to split the line, a \r has to be used. Yes, this is inconsistent, and it works differently in similar tools like sed, but that's unfortunately how it is.
Notes
The \n doesn't insert a space, but the special <NL> character, which usually is shown as ^#.
The \<code.\> isn't right; to match a literal period, you have to escape it: \.. Else, it matches any character. Likewise, the . usually isn't a keyword character, so the \> boundary wouldn't match.
You don't need to repeat the match text in the replacement, you can use & for it. Also read up on capture groups (:help /\() and the submatch references :help s/\1. This is a better way:
:%s/\<code\./&\\n/gc
(I don't see a problem with the second substitution.)

You want to insert the two-character sequence \n, not a literal newline (the latter would create a syntax error).
A sample line to be changed is:
printf("This is my d code.", x);
One problem with your attempt:
:%s/\<code.\>/code.\n/gc
is that there is no word boundary between the . and the " following the word code. The other problem is that \ in the target is used to escape special characters (for example you can refer to a / character as \/), so the \ must itself be escaped.
This should do the job:
:%s/\<code\."/code.\\n"/gc
A more general solution might be:
:g/printf/s/"/\\n"/egc
which offers to replace " by \n" on each line that contains printf -- but that will miss any printf calls that span more than one line.
As for replacing the d by %d, the command you have in your question:
:%s/\<d\>/%d/gc
is correct.

Related

How to pad strings inside curly braces with odd number of character with a single space?

We have many \foo{something}. As the string inside the curly braces contains odd number of character, we want to add a space after the string. The result will be \foo{something }. We only want odd number of characters only. For example, in \foo{string} the string inside the curly braces has even number of character, then we do not add a space.
What I have tried:
a dot means a character, two dots means two characters
asterisk means repeat 0 or more times
Then, [..]*. means 1, 3, 5 ... characters.
Then, \foo{[..]*.} will be my matching sequence.
Then, :%s/\foo{[..]*.}/\foo{[..]*. }/g will add the space we want.
But we failed.
This cmd should do:
:%s/\\foo{\zs[^}]\+\ze}/\=substitute(submatch(0), '$', len(submatch(0))%2?' ':'','g')/
:%s/\\\w\+{\([^}]\{2}\)*[^}]\zs\ze}/ /g
Explanation:
Find pairs of characters (\([^}]\{2}\)*) followed by another character ([^}]) in between a macro \\\w\+{...}. Then do a substitution adding an additional space.
Glory of details:
\\\w\+{...} find macros of the pattern \foo{...}
Look for character that does not match an ending curly brace, [^}]
Look for pairs of non-}'s, \([^}]\{2}\)*
Find an odd length string by finding pairs and then finding one more, \([^}]\{2}\)*[^}]
Use \zs and \ze to set where the start and end of the match
Use a space in the replacement portion of the substitution to add additional space and thereby making the string even in length
Fore more help see:
:h :s
:h :range
:h /\[]
:h /\(
:h /\zs
:h /\w
:h /star
:h /\+
This should work
:%s/\v[(\{(\w{2})*) ]#<!}/ }/g
break down:
%s " run substitute on every line
\v " very magic mode
[(\{(\w{2})*) ] " matches every `{` followed by an equal number of word
characters and space, since you don't want to add a space again everytime
you run it.
#<!} " negative lookahead, matches all } not following the pattern before
Update
To solve the precise problem as you can read in the comments, the following command helps.
g/^\\foo/s/\v(\{([^}]{2})*)#<!}/ }/g
Changes:
g/^\\foo/... " only run it on lines starting with \foo
[^}] " it does now match all characters between { and } not only word
characters.
Pitfalls: won't work correct with multiple braces on the line ( \foo{"hello{}"} and \foo{string} {here it would also match} f.e. will fail). if one of these is a problem. just tell me

vim - how to find lines with specified amount of specified characters

I have 100k lines file and some lines has unescaped apostrophe, like:
""Luis" number 4"
I want:
"\"Luis\" number 4"
so how can I find all lines having more than 2 " character. is it possible to do it easly in vim ? otherwise it is for simple script task.
If you just want to find such lines you can search as follows:
/.*".*".*".*
where .* will match zero or more characters and " is the literal quote you're looking for.
The first and last .* patterns aren't strictly necessary, but they make sure the whole line is highlighted when a search is found.
You can try
:%s/""\([^"]*\)"\(.*\)"/"\\"\1\\"\2"/
%s/\v"(.*)"(.*)"(.*)"/"\1\\"\2\\"\3"/
Breaking this down:
%s: Substitute on every line
\v: Very magic (don't have to escape all those parens in regex)
"(.*)"(.*)"(.*)": Anything in quotes anywhere inside anything in quotes
And replace with a quote, everything up to the opening inner quote (\1), an escaped quote, everything inside the inner quotes (\2), another escaped quote, then the rest (\3) and a close quote.

How do I remove the last six characters of every line in Vim?

I have the following characters being repeated at the end of every line:
^[[00m
How can I remove them from each line using the Vim editor?
When I give the command :%s/^[[00m//g, it doesn't work.
You could use :%s/.\{6}$// to literally delete 6 characters off the end of each line.
The : starts ex mode which lets you execute a command. % is a range that specifies that this command should operate on the whole file. The s stands for substitute and is followed by a pattern and replace string in the format s/pattern/replacement/. Our pattern in this case is .\{6}$ which means match any character (.) exactly 6 times (\{6}) followed by the end of the line ($) and replace it with our replacement string, which is nothing. Therefore, as I said above, this matches the last 6 characters of every line and replaces them with nothing.
I would use the global command.
Try this:
:g/$/norm $xxxxxx
or even:
:g/$/norm $5Xx
I think the key to this problem is to keep it generic and not specific to the characters you are trying to delete. That way the technique you learn will be applicable to many other situations.
Assuming this is an ANSI escape sequence, the ^[ stands for a single <Esc> character. You have to enter it by pressing Ctrl + V (or Ctrl + Q) on many Windows Vim installations), followed by Esc. Notice how this is then highlighted in a slightly different color, too.
It's easy enough to replace the last six characters of every line being agnostic to what those characters are, but it leaves considerable room for error so I wouldn't recommend it. Also, if ^[ is an escape character, you're really looking for five characters.
Escape code
Using ga on the character ^[ you can determine whether it's an escape code, in which case the status bar would display
<^[> 27, Hex 1b, Octal 033
Assuming it is, you can replace everything using
:%s/\%x1b\[00m$//gc
With \%x1b coming from the hex value above. Note also that you have to escape the bracket ([) because it's a reserved character in Vim regex. $ makes sure it occurs at the end of a line, and the /gc flags will make it global and confirm each replacement (you can press a to replace all).
Not escape code
It's a simple matter of escaping then. You can use either of the two below:
:%s/\^\[\[00m$//gc
:%s/\V^[[00m\$//gc
If they are all aligning, you can do a visual-block selection and delete it then.
Otherwise, if you have a sequence unknown how to input, you can visually select it by pressing v, then mark and yank it y (per default into register "). Then you type :%s/<C-R>"//g to delete it.
Note:
<C-R>" puts the content of register " at the cursor position.
If you yanked it into another register, say "ay (yank to register a - the piglatin yank, as I call it) and forgot where you put it, you can look at the contents of your registers with :reg.
<C-R> is Vim speak for Ctrl+R
This seems to work fine when the line is more than 5 chars long:
:perldo $_ = substr $_, 0, -5
but when the line is 5 or less chars long it does nothing.
Maybe there is a easy way in perl to delete the last 5 chars of a string, but I don't really know it:)
Use this to delete:
:%s/^[[00m//gc

How do I capture the output of a vim command in a register, without the newlines?

This is related to this question:
How to redirect ex command output into current buffer or file?
However, the problem with using :redir is that it causes 3 or 4 extra newlines in front of the output, and they appear to be difficult to remove using the substitute function.
For example, if I do the following:
:redir #a
:pwd
:redir END
The contents of #a consist of three blank lines and then the normal expected output.
I tried to post process with something like this:
:let #b = substitute(#a, '\s*\(.\{-}\)\s*', '\1', '')
But the result is that #b has the same contents as #a.
Does anyone know a more effective (i.e. working) way to postprocess, or a replacement for :redir that doesn't have those extra lines?
The value in the b register is unchanged from the value in the a register because your regexp is failing to match.
You need to write grouping parentheses and the opening repetition brace with with backslashes.
See :help /magic; effectively, the magic option is always on for substitute() regexps.
\s only matches SP and TAB (not LF); but \_s does include LF (alternately, you could use \n to just match LF).
You need to anchor the end of the expression so that the \{-} does not “give up” without matching anything (everything but the initial newlines unmatched, and thus unreplaced from the input string).
Here is a modified version of your substitution:
:let #b = substitute(#a,'\_s*\(.\{-}\)\_s*$','\1','')
It may be simpler to just think about deleting leading and trailing whitespace instead of matching everything in between. This can be done in a single substitution by using the g substitution modifier (repeated substitutions) with a regexp that uses the alternation operator where one alternate is anchored to the start of the string (%^) and the other is anchored to the end of the string (%$).
substitute(#a,'\v%^\_s+|\_s+%$','','g')
This regexp uses \v to avoid having to add backslashes for %^, +, |, and %$.
Change both occurrences of \_s to \n if you just want to trim leading/trailing newlines (instead of SP, TAB, or NL).

How to find & replace many expressions with one in Vim?

I am copy-pasting an example from a PDF to Vim and I have to replace all “ and ” with "
and all ‘ and ’ with ' so that the code works.
Well that will probably seem easier to understand:
I want to replace all foo and bar with foobar simultaneously.
Try this in vi:
:1,$s/[“”]/"/g
then
:1,$s/[‘’]/'/g
Use tr as a filter:
Unix way:
:%!tr “”‘’ \"\"\'\'
If you want to replace all "foo"s and all "bar"s with "foobar" you can use this:
%s/\v<(foo|bar)>/foobar/g
This will replace the "foo"s and the "bar"s but will leave any "foobar"s alone.
%s/ - substitute across the whole file
\v - use very magic regex syntax (see :help magic for more info)
< - match a left word boundary
(foo|bar) - foo or bar
> - match a right word boundary
/foobar/ - replacement string
g - globally (will happen for every occurrence, not just the first on the line)
Note that if you are just dealing with punctuation you'll probably want to remove the word boundary parts of this regex or it won't work.

Resources