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
Related
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
I have text like this:
w ky,
wyz,
wyy,
wj,
w w,
and I want to change it to this:
"w ky",
"wyz",
"wyy",
"wj",
"w w",
I do it now using:
record a macro to insert double quota in one line, then go to next line qa0wi"$i"j
then just type 4#a
Yes, it works, but is there an easier way to do this?
There is an easier way. You can use the norm command. I would recommend this:
Visually select all of the lines
Type
:norm I"<C-v><esc>$i"<cr>
When you actually type this (before hitting enter), the text that should be shown in your command line is:
:'<,'>norm I"^[$i"
The norm command tells vim to simulate a set of normal mode keystrokes on certain lines. In this case, the command is:
:'<,'> " On every line in the visual selection:
norm " Do the following as if typed in normal mode:
I"<esc>$i" " Insert an '"', escape, then insert a '"' at the end (before the comma)
You can also do this without using a visual selection, by typing <n>:norm ..., and the command will apply the current n lines. (the current line and the next n-1 lines)
Doing a "very magic search \v" we can search...
\v(\w ?\w+),
\v ........... starts very magic search mode
( ........... starts group one
\w ........... any word
? ........... optional space
+ ........... one or more
) ........... ends group one
After testing the search we can pass into our command or
use the last search by placing two slashes on the search pattern
%s/\v(\w ?\w+),/"\1",/g
%s//"\1",/g
everything matched on group one can be referred by \1.
Do a basic multi-line edit at the front then do a string replace on , with ",.
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.
I have several lines of text, like this
text1*textX*,text2
and I would like to move the text between the ** markers to the start of the line, so it looks like this
textX "text1" "text2"
How can I do that in the command line?
Try below command:
s/^\(.*\)\*\(.*\)\*/\2 \1/
It modifies text1*textX*,text2 to textX text1,text2
if has literals * you need put them inside [*]
:%s,\v^([^ ]*)\s\+([^ ]*).*,\2 \1,g
: ................. command
% ................. whole file
s ................. replace
^ ................. begining of line
, ................. search and replace delimiter (comma exchanging by bar)
\v ................ very magic, see :h very-magic
([^ ]*) ........... group 1 (group here) everything except space
\s\+ .............. one or more spaces
([^ ]*) ........... group 2 (group here) everything except space
\s\+ .............. one or more spaces
.* ................ zero or more characters
\2 ................. back reference to group 2
\1 ................. back reference to group 1
, .................. ending replace
g .................. global
Another approach...
On the above sample I would do (in normal mode):
0dt*f*p
. 0 : goes to start of line
. d : starts delete (waits for movement or text object)
. t* : moves the cursor to the first asterisk and yanks the deleted text to the unnamed register
. f* : moves the cursor to the second asterisk
. p : pastes the contents of the unnamed register immediately after the second asterisk
References:
:h f
:h t
Naturally, it does take a bit of practice before you're able to conjure up the power of these two commands and they becomes second nature so you can use them in real world situations.
I sometimes find this approach more effective than typing a regex on Vim's command line.
More than a couple of lines:
qzq:#=n
Where n is the repetition factor.
While Niraj Nawanit's answer might give you what you're looking for, this gives you exactly what you asked for:
%s/\([^*]*\)\*\(.*\)\*,\([^[:space:]]*\)/\2 "\1" "\3"/
I always wanted to know, how you can substitute within given parameters.
If you have a line like this:
123,Hello,World,(I am, here), unknown
and you wnat to replace World with Foobar then this is an easy task: :%s/World/Foobar/
Now I wonder how I can get rid of a , which is wihtin the ( ).
Theoretically I just have to find the first occurance of ( then substitute the , with a blank until ).
Try lookahead and lookbehind assertions:
%s/([^)]*\zs,\ze.*)//
(\zs and \ze tell where pattern starts and end)
or
%s/\(([^)]*\)\#<=,\(.*)\)\#=//
The first one is more readable, the second one uses \( ... \) groupings with parentheses inside groups which makes it look like obfuscated, and \#<= which apart from being a nice ASCII-art duck is the lookbehind operator, and \#= that is the lookahead operator.
References: :help pattern (more detail at :help /\#=, :help /\ze, etc.)
You use the GUI and want to try those commands? Copy them into the clipboard and run :#+ inside Gvim.
Modifying slightly the answer of #Tom can give you a quite good and "a bit" more readable result :
%s/\(.*\)(\(.*\),\(.*\))\(.*\)/\1(\2\3)\4/
That way you will have : in \1 will store what is at the left outside of the parenthesis, \4 what is at the right outside of the parenthesis and \2 and \3 what is inside the parenthesis, respectively on the left (\2) and on the right (\3).
With that you can easily swap your elements if your file is organised as column.
You can also select the text you want to change (either with visual or visual-block modes) and enter the : to start the replace command. vi will automatically start the command with :'<,'> which applies the command to the selected area.
Replacing a , can be done with:
:'<,'>s/,/ /g
For your example, this is the same thing as suggested by #ubuntuguy
%s/\(.*\)(\(.*\),\(.*\)/\1(\2\3
This will do the exact replacement you want.
Yet another approach, based on the fact that actually you want to substitute only the first occurrence of , inside the parenthesis:
:%s#\((.\{-}\),#\1 #
Explanation:
:%s for substitution in the whole file (don't use % if you want to work only with the current line)
we can use # or : as a delimiter to make the command more readable
in (.\{-} we ask to find any symbol (dot) after the left parenthesis and the rest stands for 0 or more occurrence (as few as possible) of this symbol. This expression is put inside \(...\) to be able to refer to this group as \1 in the future.