7

I have the line number 55 in a text file which I want to move just before line number 23 in the same text file. I know that you can move lines up by a certain number of lines 1, 2 but is it possible to append or prepend a line to another line instead of the verbose way of moving lines up or down a textfile?

I am open to answers using vim, sed or any other command line tool but the more concise the better

update:

The sed command i inserts text before a line which is similar to what I am looking for except that I want to insert a line before a line

  • both mentioned links have solutions done by ed, have you tried them? – RomanPerekhrest Jul 21 at 19:27
  • @RomanPerekhrest , I'm not familiar with ed but I also missed those solutions because I didn't scroll down far enough – MyWrathAcademia Jul 21 at 19:45
  • You might want to check out the Vi and Vim Stack Exchange for questions on Vim! – filbranden Jul 22 at 6:51
11

A scriptable editor makes this pretty straight-forward!

printf '%s\n' '55m22' 'wq' | ed -s input

This sends two commands to ed (editing the file named input):

  1. 55m22 -- move line 55 after line 22
  2. wq -- save the file back to disk and quit.
  • It worked almost perfectly but I didn't read your answer fully so it moved line 55 after line 22, which is not a big deal just something to keep in mind. As for the command you posted: Why did you separate the two commands with a line break, usually when piping from one command to another the second command connected to the end of the pipe receives the output from the pipe as a series of arguments e.g. in a directory that contains directory1 and directory2 echo * | ls -l is equivalent tols -l directory1 directory2. Why not printf '%s ' '55m22' 'wq' | ed -s input'? – MyWrathAcademia Jul 21 at 19:39
  • @MyWrathAcademia that's not how pipes work and also not how ls works. The word splitting is usually done by the shell alone, but the shell does not modify what goes into the pipe. Pipes transfer raw data, it's up to the target program what to do with it. If ed expects one command per line, that is what you have to provide. – frostschutz Jul 21 at 19:47
  • I used 22 because the move command moves the addressed line after the target line and you wanted it to land before line 23. – Jeff Schaller Jul 21 at 19:57
  • @frostschutz , thanks for the correction, can you specify which part of my description of a pipe was misinformed? Is it the bit about a series of arguments or the command after the pipe being connected to the end of the pipe? As for the "word splitting being done by the shell alone", isn't the command line user the one that specifies the word splitting to the shell in the form of \n (line feed), ` ` (white space), \r (carriage return) etc.? – MyWrathAcademia Jul 21 at 19:57
  • 1
    The line break you see in the printf format sends the commands with a newline so that ed sees them as two separate commands, just as if you had run ed interactively. – Jeff Schaller Jul 21 at 19:58
4

A little shorter:

ex input <<<"55m22|wq"
  • If you are assuming this level of shell support, one could also write ed -s input <<< $'55m22\nwq'. The main benefit to using ex would be the ability to use a single pipe-delimited command rather than a series of newline-terminated commands. Otherwise, you would write printf '55m22|wq\n' | ex input, which saves three characters over printf '55m22\nwq\n' | ed -s input. – chepner Jul 22 at 17:13
3

It's somewhat longer in vi than in ed:

vi input
55Gdd23GPZZ

55G ... go to line 55
dd ... delete one line
23G ... go to line 23
P ... paste the deleted line before line 23
ZZ ... write file and exit

  • 8
    vi also has the :m command, same as ed, so :55m22 is also possible in vi. – filbranden Jul 22 at 6:57
  • 1
    Thank you, @filbranden! – Jim L. Jul 22 at 16:58
  • 2
    Historically, vi was a refinement of ex, which itself was a refinement of ed. – chepner Jul 22 at 17:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.