How to search for a word but replace characters in the line above in gvim - search

In the code below, I want to replace/remove the , from the line above .VSS(VSS).
It is at multiple places in the file. I have basic knowledge of gvim and I could not figure out how to just search and then pipe it with replace.
ANTENNABWP7THVT ANTENNABWP7THVT_spr_gate156 (
**.I(LTIELO_NET),
.VSS(VSS),**
.VDD(VDD));

Matching each line that contains .VSS(VSS) and doing something with it can be done with :global. You then want to address the line above it; that's a :help :range: .-1 (or short -1). And removal of a (all with the /g flag) comma can be done with plain :substitute. Taken together:
:global/\.VSS(VSS)/-1substitute/,//

Related

How to add text before the first occurence of a character in Vim?

I have the text
af_ZA_work_013_A;135.300;150.203;Spreker-A;;;[no-speech] #mm
af_ZA_work_013_A;135.300;150.207;Spreker-B;;;[no-speech] #something
I want to add .wav before the first ; in each line, so I would get
af_ZA_work_013_A.wav;135.300;150.203;Spreker-A;;;[no-speech] #mm
af_ZA_work_013_A.wav;135.300;150.207;Spreker-B;;;[no-speech] #something
How can I do this?
s/search_regex/replace_regex/ will linewise execute your find and replace.
By default, this is done only on the current line, and only on the first match of search_regex on the current line.
Prepending % (%s/search/replace/) will execute your find and replace on all lines in the file, doing at most one replacement per line. You can give ranges (1,3s will execute on lines 1-3) or other line modifiers, but this isn't relevant here.
Appending g (s/search/replace/g) will do multiple replaces per line. Again, not relevant here, but useful for other scenarios.
You can search for ; and replace with .wav; (there are ways to keep the search term and add to it using capture groups but for one static character it's faster to just retype it).
TL;DR: :%s/;/.wav;/ does what you want.

searching for a pattern and placing it within another in vim

I have about 256 lines in a text file that look like /*0*/L"", I want to remove the last , and then put the remaining as a function argument code.append(/*0*/L""); I tried doing it with vim but I don't have much experience in it. how can we place something within something else in vi or vim?
:%s#\v(/\*0\*/L""),#code.append(\1);#
:%s : substitute all lines
# : alternative separator
\v : use very magic mode (see :h magic)
(/\*0\*/L""), : capture the regex, excluding the trailing comma
\1 : insert first captured group
this line would do the substitution on all lines in your buffer, only if the line ending with comma. No matter you had /*0*/L"", or /*123*/L"",
%s/\v(.*),$/code.append(\1)/
if you want to shrink the sub on certain pattern, change the .* part in the above cmd to fit your needs.

Write output from command line into file in vim

I would like to insert at the end of each line the number of alphabetic characters on that line. To do this on one line is easy. I search using :s/\a//gn and get the occurrence of alphabetic characters in the command line and then A and space and enter the number.
My problem arises when I have so many lines that it becomes extremely tedious to do this. I am trying to create a macro but am having difficulty getting command line output into it. Is there a way to do this without resorting to *nix commands? I have access to a *nix box but not all the time.
So if my file had the following content:
abc2d4s
jd4a5ag
jdf7fjf
abdd5ff
I would like the output to look like this:
abc2d4s 5
jd4a5ag 5
jdf7fjf 6
abdd5ff 6
I was thinking if there was a way to get the replace output piped into the register somehow but cannot figure out how to do it, but maybe there is a better way.
You can capture the output of the :s///gn command with :redir, but in this case, I would rather implement the counting via substitute() and :help sub-replace-expression:
:%s/.*/\=submatch(0) . ' ' . len(substitute(submatch(0), '\A', '', 'g'))/
This matches the entire line (.*), then removes all non-alphabetic characters (\A), and appends the length of the result. Note: Works only for ASCII characters (but \a covers only those, anyway)!
this cmd should give you that output:
%s/.*/\=submatch(0).' '.(len(submatch(0))-len(substitute(submatch(0),'\a','','g')))
One way to do that would be to use a simple macro:
:%norm A <C-v><C-r>=col('.')-2<C-v><CR>
which should look like:
:%norm A ^R=col('.')-2^M
where we enter insert mode at the end of each line and insert a space followed by the column number of the last character.
A variant:
:%norm A^R=" ".len(getline('.'))^M

Vim: How to delete the same block of text over the whole file

I'm reviewing some logs with Java exception spam. The spam is getting is making it hard to see the other errors.
Is is possible in vim to select a block of text, using visual mode. Delete that block every place it occurs in the file.
If vim can't do it, I know silly question, vim can do everything. What other Unix tools might do it?
Sounds like you are looking for the :global command
:g/pattern/d
The :global command takes the form :g/{pat}/{cmd}. Read it as: run command, {cmd}, on every line matching pattern, {pat}.
You can even supply a range to the :delete (:d for short) command. examples:
:,+3d
:,/end_pattern/d
Put this togehter with the :global command and you can accomplish a bunch. e.g. :g/pat/,/end_pat/d
For more help see:
:h :g
:h :d
:h :range
Vim
To delete all matching lines:
:g/regex/d
To only delete the matches themselves:
:%s/regex//g
In either case, you can copy the visual selection to the command line by yanking it and then inserting it with <C-r>". For example, if your cursor (|) is positioned as follows:
hello wo|rld
Then you can select world with viw, yank the selection with y, and then :g/<C-r>"/d.
sed
To delete all matching lines:
$ sed '/regex/d' file
To only delete the matches themselves:
$ sed 's/regex//g' file
grep
To delete all matching lines:
$ grep -v 'regex' file
grep only operates line-wise, so it's not possible to only delete matches within lines.
you can try this in vim
:g/yourText/ d
Based on our discussion in the comments, I guess a "block" means several complete lines. If the first and last lines are distinctive, then the method you gave in the comments should work. (By "distinctive" I mean that there is no danger that these lines occur anywhere else in your log file.)
For simplifications, I would use "ay$ to yank the first line into register a and "by$ to yank the last line into register b instead of using Visual mode. (I was going to suggest "ayy and "byy, but that wold capture the newlines)
To be on the safe side, I would anchor the patterns: /^{text}$/ just in case the log file contains a line like "Note that {text} marks the start of the Java exception." On the command line, I would use <C-R>a and <C-R>b to paste in the contents of the two registers, as you suggested.
:g/^<C-R>a$/,/^<C-R>b$/d
What if the yanked text includes characters with special meaning for search patterns? To be on the really safe side, I would use the \V (very non-magic) modifier and escape any slashes and backslashes:
:g/\V\^<C-R>=escape(#a, '/\')<CR>\$/,/\V\^<C-R>=escape(#b, '/\')<CR>\$/d
Note that <C-R>= puts you on a fresh command line, and you return to the main one with <CR>.
It is too bad that \V was not available when matchit was written. It has to deal with text from the buffer in a search pattern, much like this.

How to append every third line in Vim?

I'm not at all familiar with Vim but I'm working with large text files (~1G) and my standard text editors weren't cutting it.
My files are currently in this format:
Arbitrary_title_of_sequenceA
SEQ1SEQ1SEQ1SEQ1
SEQ2SEQ2SEQ2SEQ2
Arbitrary_title_of_sequenceB
SEQ1SEQ1SEQ1SEQ1
SEQ2SEQ2SEQ2SEQ2
I need a convenient way of appending the "SEQ2" line to the "SEQ1" line like so:
Arbitrary_title_of_sequenceA
SEQ1SEQ1SEQ1SEQ1SEQ2SEQ2SEQ2SEQ2
Arbitrary_title_of_sequenceB
SEQ1SEQ1SEQ1SEQ1SEQ2SEQ2SEQ2SEQ2
Considering the size of these files, doing each line separately isn't really an option. Any help would be much appreciated!
What about providing a correct sample to begin with?
:g/SEQ1/norm Jx
does what I think you want.
:g/SEQ1 is the :global command which allows you to act on each line containing the pattern SEQ1. See :help :global.
norm is the :normal command that you use to perform a normal mode command, here on every line matched by :g/SEQ1. See :help :normal.
After that comes the normal command in question:
J is used to join the current line with the line below.
x is used to remove the <Space> automatically added by Vim.
:1,$s/\(.*\n\)\(.*\)\n\(.*\n\)/\1\2\3/
1,$ -> range is all file
s/PAT1/PAT2/ -> substitute PAT1 with PAT2
.* -> match any character except new line
\n -> match new line
\(PAT1\) -> capture/remember the string that matched PAT1
\1,\2,\3 -> refers to the captured string for captures in order
Also using sed instead of vim should be faster:
sed -i 'n;N;s/\n/ /' input_file
This can be summarized as:
Read a line
Read another line and print previous line (n)
Read another line and append it to the previous line (N)
find the first newline and change it to space (s/\n/ /)
print the line (or merged lines)
I think romainl's solution is the best if you have a reliable "SEQ1" pattern you can grab onto. If not and you want to literally join every third line, you could easily do this with a macro:
qqjJxjq
Hit G to see how many lines are in the file and just repeat the macro that many times (it doesn't matter that it's higher than you need). So if the file was 1000 lines you could do 1000#q. This kind of solution is easy to remember and integrate into your normal workflow.

Resources