Search and append text at the end of the line - vim

I have a file in which there is a command on each line. Within the command there is a line which is always P0......xml. I want to append that P0.... to the end of each line with a >> operator in front and .log at the end.
For example,
If a command looks like this:
abcdefg hijkl mno P0qrstuv.xml wxyz abc
I would like to make it:
abcdefg hijkl mno P0qrstuv.xml wxyz abc >> P0qrstuv.log
Please explain your answer as precisely as possible.

One solution would be to use the substitute command in Ex mode. This should do it.
:%s/\v(P0.+\.xml).*/& >>\1.log/
: puts you into Ex mode
% act on the whole file
s does the substitution
\v specifies that the regex will "very magic" and not the regular vim regex.
(P0.+\.xml) grouping of text the file name
& inserts what was matched
\1 inserts the first grouping (if you would have more than one you could do \2 \3 etc..)

Related

How to split the first 2 columns from the line in vim?

xyz mnl pqt aaaa ccc
yz mn ats aa cbc ddd eee ggg
I have a file with each line like the above. Each column is split with a space. I want to remove all other columns except the first 2 columns, namely:
xyz mnl
yz mn
I tried a number of patterns but they don't work.
For a more Unix-y solution:
:%!awk '{print $1, $2}'
Where:
:%!<cmd> filters every line in the buffer through external command <cmd>.
See :help :range and :help :!.
awk '{print $1, $2}' is that external command.
'{print $1, $2}' is a short AWK script that prints the first and second fields of each line.
For more information on awk: $ man awk.
One fairly easy way to do it is to use the command :normal with a Normal mode command that would delete anything past the second field. For example, you could use 2f<Space> to seek to the second space, followed by D (or the equivalent d$) to delete until the end of the line.
You can then use that command with a range, for example :% to perform it on the whole buffer, or perhaps select the lines with a Visual selection and then when you start the Ex command with :, Vim will automatically insert :'<,'> which means the lines in the Visual selection.
So, for example, performing the substitution on the whole buffer:
:%norm 2f D
See :help :normal for more details.
Using the command line
:%norm wwhD
If a line in the file separated by a single whitespace character, then you can simply done the job using :substitute command:
:%s/^\S\+ \S\+\zs.*$//
The point here is that \zs to start matching columns you want to remove.
With \zs you don't need to save the first 2 words with \(\S\+ \S\+\).

replace a string with other string in the same line

Vi editor
Input file text format:
'': hello.Code1
'': hello.Code2
'': hello.Code3
Required output text format:
'Code1': hello.Code1
'Code2': hello.Code2
'Code3': hello.Code3
Idea is I have to copy all the values after "." to the single quotes ''. I can use Vi or SED etc. Linux based. or MAC based.
I have more that 2000 lines in the text file
Thanks
You can use a macro in vim. Something like:
/\.^Mly$?'^MPj0
Assuming you're at the start of the first line. Start recording. To record into the q register, hit qq and then:
i) Search for the dot
/\.^M
ii) Go one character to the right, and yank to the end of the line
ly$
iii) Reverse search the quote: '
?'^M
iv) Paste the content and go down a line and move to the start.
Pj0
You can then just repeat the action. Assuming you recorded it in the q register:
2#q
(Note: ^M is <Enter>)
This can be done quite simply with a substitute command and capturing groups. Try the following regex:
:%s/''\(.*\)\.\(.*\)/'\2'\1.\2
This says, Search for quotes '', followed by anything captured into group 1 \(.*\), followed by a literal dot \., followed by anything captured into group 2 \(.*\). This will put
: hello
Into group 1, and
CodeN
into group 2. So then we replace it with group 2 in quotes '\2' followed by group 1 \1, followed by a dot \. and group 2 again \2.
If you put \v at the beginning of the regex, you can get rid of a lot of the backslashes and make it more readable:
:%s/\v''(.*)\.(.*)/'\2'\1.\2
You could also do this with a %normal command. That makes a set of keystrokes be applied to every line in the buffer. I would try this:
:%norm f.ly$0p
This says, On every line, do the following keystrokes :%norm Move forward to a '.' f., move one character to the right l, yank everything to the end of this line y$, move to the beginning of this line 0, and paste what we just yanked p

How to let Vim process my command backforward?

Suppose I have 5 lines of text, if I input some commands to let vim process each line, Vim will process the text one by one, first line, second line, ... the last line. what I want is to let Vim process my text in reverse order. that is the last line first, then the 4th line, and at last the first line.
Why I need this?
I have the following text
1234567890
abc
123
def
1234567890
123456789
I want to remove the newline symbol(\n) from lines which contains 3 characters. so after processing,I will get the following text
1234567890
abc123def1234567890
123456789
It seems a piece of cake, I use the following command
:%s/\v(^\w{3})\n/\1/
But what i got is
1234567890
abc123
def1234567890
1234567890
Why? I guess vim first remove \n from the second line, then this line has text abc123, now vim will not remove \n after 123, since it's not 3 characters now, so vim process the next line def, and remove \n from it, that's the result i got.
If vim can process from back to front, this will not happen and I can got the result I want.
BTW, I can get the expected result in other ways, I just want to know whether this is possible.
Explicitly loop over the range of lines (e.g. the visually selected ones) backwards, then execute the command on each line. I've used :join here instead of the :substitute with a newline:
:for i in range(line("'>"), line("'<"), -1)| silent execute i . 'g/^\w\{3}$/join!' | endfor
Can be achieved using perl:
while (<>) {
chomp if (/^...$/);
print;
}
In this case it is easier to use the :global command to join the lines.
:g/^\w\{3}$/normal! gJ
The command gJ joins the current line with the following line without inserting any spaces. The global command above calls gJ on each line containing only three characters. It works by marking all the matches first, before performing the operation, so the problem of looping is avoided.
this line should do what you want:
:%s/\v(\_^\w{3}\n)+/\=substitute(submatch(0),"\n","","g")/
if you want to do it simpler with external command, e.g. awk, you could:
%!awk '{printf "\%s", length($0)==3? $0:$0"\n"}'

Inserting extra line breaks using VIM

I have an interview transcript with continuous text. At times, the names of the person speaking are written (Aron:, Kalle:, Tomas: etc.). I want to insert a line break before every name that is followed by a colon (:) (names, which I specify).
How can I script this in VIM so that when I run the command, it goes through the entire text file and insert those extra linebreaks?
In other words, I want to turn this:
Aron: bla, bla, bla
Kalle: yes, yes, yes
into:
Aron: bla, bla, bla
Kalle: yes, yes, yes
Try this simple command:
:g/^/pu_
g/^/ will match every line, then exec command below.
pu _ will put the text from register _(the black hole register) after current matched line.
You can also use the :substitute command:
:%s/$/\r
Yet another one which uses external sed:
:%!sed G
All commands have the same length. Pick one you like.
Try this
:%s#^\(\w*:\)#\r\1#g
- % : serach in all lines
- s : search and replace command
- # : separators (I perfer '#' to '/')
- \(\w*:\) : grep your required format (Aron:, Kalle:, Tomas: etc.) and store in \1
- \r : for inserting a line
- g : global search and replace

How to add a line after every few lines in vim

I wanted to add a line after every 3 lines in a file (having about 1000 lines) using vim editor. Can someone help me out?
Thanks,
Alisha
there is a vim-specific regular expression to do that
:%s/.*\n.*\n.*\n/\0\r/g
%s is vim ex command to substitute in the whole file
.*\n is a line including the end of line
\0 is the entire matched expression
\r vim way to say add a new line (not \n as one would expect)
Edit: if you want anything else than a new line, just put the text in front of the \r (properly regex escaped, if it contains some regex characters)
You can use a macro. The complete process looks like:
qq " start recording to register q (you could use any register from a to z)
o " insert an empty line below cursor
<Esc> " switch to normal mode
jjj " move the cursor 3 lines downward
q " stop recording
Then just move to the start line and type 1000#q to execute your macro 1000 times.
" insert a blank line every 3 lines
:%s/\v(.*\n){3}/&\r
: .............. command
% .............. whole file
s .............. replace
/ .............. start pattern that we will replace
\v ............. very magic mode, see :h very-magic
(.*\n) ......... everything including the line break
{3} ............ quantifier
/ .............. start new pattern to replace
& .............. corresponds to the pattern sought in (.*\n)
\r ............. add line break
source: http://www.rayninfo.co.uk/vimtips.html
I would do this:
:%s/^/\=(line(".")%4==0?"\n":"")/g
this works if your requirement changed to " *add a new blank line every 700 line*s" :) you just change the "4"
P.S. if I need do this, I won't do it in vim. sed, awk, could do it much simpler.

Resources