How to copy multiple lines one under each line separately? - vim

Sorry for the bad english, see this example:
original
a
line01
line02
line03
line04
b
want to become:
a
line01
line01
line02
line02
line03
line03
line04
line04
b
a and b are irrelevant.
I can copy one line and paste, and repeat. Is there any simple solution? like one command?

Using a global command, this could easily be done like this
:g/^/t.
Breakdown
:g start a global command
/^ search for a begin of line (every line matches)
/t. copy the current line

You could also write a vim macro-
With your cursor at line 0, column 0; record a macro, store in register a
qa
Copy the current line; paste it below; move your cursor down to the next line
yypj
Save the Macro
q
Now run the a macro N number of times (it will stop at the bottom of the file regardless)
3#q

For funsies a sed solution:
$ sed 'p' input.txt > output.txt
Using filter, :!, inside of Vim:
:%!sed p
Obligatory awk solution: awk '1;1' input.txt > output.txt.

Related

How to use m with the ed function in a Bash Script [duplicate]

I just need to move a line up in sed. I can select the line with
sed -i '7s///'
I need to move line 7 up 2 lines so it will be line 5.
I can't find anything on the internet to do this without complicated scripts, I can't find a simple solution of moving a specific line a specific number of times.
seq 10|sed '5{N;h;d};7G'
when up to line 5 append next line(line 6) into pattern space then save them into hold space and delete them from pattern space; up to line 7 then append the hold space content("5\n6") behind the line 7; now, pattern space is "7\n5\n6";finally,sed will print the pattern space at the end of current cycle by default(if no "-n" parameter)
ed is better at this, since it has a "move" command that does exactly what you want. To move line 7 to be the line after line 4, just do 7m4. ed doesn't write the data back by default, so you need to explicitly issue a w command to write the data:
printf '7m4\nw\n' | ed input
Although it is perhaps better to use a more modern tool:
ex -s -c 7m4 -c w -c q input

Sed move a line

I just need to move a line up in sed. I can select the line with
sed -i '7s///'
I need to move line 7 up 2 lines so it will be line 5.
I can't find anything on the internet to do this without complicated scripts, I can't find a simple solution of moving a specific line a specific number of times.
seq 10|sed '5{N;h;d};7G'
when up to line 5 append next line(line 6) into pattern space then save them into hold space and delete them from pattern space; up to line 7 then append the hold space content("5\n6") behind the line 7; now, pattern space is "7\n5\n6";finally,sed will print the pattern space at the end of current cycle by default(if no "-n" parameter)
ed is better at this, since it has a "move" command that does exactly what you want. To move line 7 to be the line after line 4, just do 7m4. ed doesn't write the data back by default, so you need to explicitly issue a w command to write the data:
printf '7m4\nw\n' | ed input
Although it is perhaps better to use a more modern tool:
ex -s -c 7m4 -c w -c q input

yank all lines and paste at the end Vim

Such as title, I want to copy all lines and paste at the end.
BEFORE:
apple
cat
dog
sun
AFTER:
apple apple
cat cat
dog dog
sun sun
Use a substitue command
:%s/.*/& &
Where .* matches everything and & is replaced with the match (in this case the whole line)
Or if you really want to yank the lines you could use a normal command
:%norm yyPJ
Which is run the command yyPJ on every line in normal mode.
Note: These commands will give slightly different output if there is leading whitespace.
If you're on unix-like system:
:%!paste -d' ' % -
Another unix-style answer (though I would go with any of #FDinoff's solution):
:%!awk '{print $1, $1}'
And another :normal answer because there's so many ways to enjoy skinning a cat:
:%norm y$A <C-v><C-r>"
And another one:
:%norm y$Pa<space> <-- just press the <space> bar
Another way , if your text is like this(~ represents blank)
apple
cat~~
dog~~
sun~~
It means that all word has the same numbers of colomn.
you can ctrl-v to select all and move cursor to the end of "apple" and type p to paste.

Vim copy and concatenate the lines

I got a file that looks like this:
G:\some_folder
file1.avi
file2.wav
E:\some_folder2
fileABC.avi
fileDEF.wav
I would like to transfer the file into:
G:\some_folder
G:\some_folder file1.avi
G:\some_folder file2.wav
E:\some_folder2
E:\some_folder2 fileABC.avi
E:\some_folder2 fileDEF.wav
So in other words this might work like this:
look for ^[A-Z]: copy whole line and add it at the beginning to next lines till you find ^[A-Z]:
is it possible to do that in VIM? If yes, how.
thank you
Radek
I would iterate over all lines with :global; Vim will position the cursor on the beginning of each line. Depending on which kind of line it is, I'd either yank the folder path, or paste it in front:
:%g/^/execute 'normal!' getline('.') =~ '^\S' ? 'y$' : 'P'

How can I replace a specific line by line number in a text file?

I have a 2GB text file on my linux box that I'm trying to import into my database.
The problem I'm having is that the script that is processing this rdf file is choking on one line:
mismatched tag at line 25462599, column 2, byte 1455502679:
<link r:resource="http://www.epuron.de/"/>
<link r:resource="http://www.oekoworld.com/"/>
</Topic>
=^
I want to replace the </Topic> with </Line>. I can't do a search/replace on all lines but I do have the line number so I'm hoping theres some easy way to just replace that one line with the new text.
Any ideas/suggestions?
sed -i yourfile.xml -e '25462599s!</Topic>!</Line>!'
sed -i '25462599 s|</Topic>|</Line>|' nameoffile.txt
The tool for editing text files in Unix, is called ed (as opposed to sed, which as the name implies is a stream editor).
ed was once intended as an interactive editor, but it can also easily scripted. The way ed works, is that all commands take an address parameter. The way to address a specific line is just the line number, and the way to change the addressed line(s) is the s command, which takes the same regexp that sed would. So, to change the 42nd line, you would write something like 42s/old/new/.
Here's the entire command:
FILENAME=/path/to/whereever
LINENUMBER=25462599
ed -- "${FILENAME}" <<-HERE
${LINENUMBER}s!</Topic>!</Line>!
w
q
HERE
The advantage of this is that ed is standardized, while the -i flag to sed is a proprietary GNU extension that is not available on a lot of systems.
Use "head" to get the first 25462598 lines and use "tail" to get the remaining lines (starting at 25462601). Though... for a 2GB file this will likely take a while.
Also are you sure the problem is just with that line and not somewhere previous (ie. the error looks like an XML parse error which might mean the actual problem is someplace else).
My shell script:
#!/bin/bash
awk -v line=$1 -v new_content="$2" '{
if (NR == line) {
print new_content;
} else {
print $0;
}
}' $3
Arguments:
first: line number you want change
second: text you want instead original line contents
third: file name
This script prints output to stdout then you need to redirect. Example:
./script.sh 5 "New fifth line text!" file.txt
You can improve it, for example, by taking care that all your arguments has expected values.

Resources