8

I am currently trying to automate updating the text of a file, titled original_file.txt. Imagine the file looks like the following:

common_text
### REPLACE EVERYTHING AFTER THIS LINE ###
text_that_will
be_removed
after_the_command

This file will be updated by removing all text after "Replace everything after this line", and replacing it with the text in the file replacement_file.txt. For the sake of the post, imagine that replacement_file.txt has the following text:

testing123
this_is_the_replacement_text

From what I've been able to find with sed, I can only figure out how to edit the rest of the line after a certain phrase. I want to replace the text in original_file.txt after the replacement phrase with all of the text from replacement_file.txt (I want to keep the replace line text for future updates). original_file.txt should look like this at the end:

common_text
### REPLACE EVERYTHING AFTER THIS LINE ###
testing123
this_is_the_replacement_text

Thanks in advance!

don_crissti
  • 82,805
ddantas
  • 113

7 Answers7

15

In GNU/awk:

Name the two files as arguments.

awk '{ print; } /^### REPLACE EVERYTHING AFTER THIS LINE ###$/ { nextfile; }' fn1 fn2
Paul_Pedant
  • 8,679
14

Print all lines until "replace after" line is found, then read from other file & quit:

sed '/^### REPLACE EVERYTHING AFTER THIS LINE ###$/{r replacement_file.txt
q;}' original_file.txt

  • use sed -i to save changes
  • or ... > tmp && mv tmp original
rowboat
  • 2,791
7

Using sed:

sed -n -e '1,/^### REPLACE EVERYTHING AFTER THIS LINE ###$/{ p; d; }' \
       -e 'r replacement_file.txt' \
       -e 'q' original_file.txt

The three sed blocks do this:

  1. The first block prints all lines from line 1 to the line with the special contents. I print these lines explicitly with p and then invoke d to force a new cycle to start ("print; next" in awk).
  2. After the initial lines have been outputted by the first block, the second block outputs the contents of the extra file.
  3. The editing script is then terminated.

Ordinarily, q in the third block would output the current line before quitting (this would be the line in the example data reading text_that_will), but since sed is invoked with -n, this default outputting of a line at the end of a cycle is inhibited.

The result of the above command, given your data, is

common_text
### REPLACE EVERYTHING AFTER THIS LINE ###
testing123
this_is_the_replacement_text

To update the original file, you could use sed -i ..., or redirect the output to a new file that you then replace the original with:

sed ... original_file.txt >original_file.txt.new &&
mv original_file.txt.new original_file.txt
Kusalananda
  • 333,661
  • Thank you, this worked for me, and I really appreciate the explanation.

    Quick clarification question: If instead of '### Replace everything after this line ###', I have a javascript comment which instead reads '//Replace below', how might I do that? I am having trouble writing the sed to account for the special characters '//'. Thank you once again.

    – ddantas Mar 30 '20 at 23:12
6

This will work efficiently using any awk and cat:

$ awk '{print} /### REPLACE EVERYTHING AFTER THIS LINE ###/{exit}' original_file.txt &&
    cat replacement_file.txt
common_text
### REPLACE EVERYTHING AFTER THIS LINE ###
testing123
this_is_the_replacement_text

As with any UNIX tools, to update the original just write the output to a temp file and then replace the original with that temp file:

{ awk '{print} /### REPLACE EVERYTHING AFTER THIS LINE ###/{exit}' original_file.txt &&
   cat replacement_file.txt; } > tmp && mv tmp original_file.txt
Ed Morton
  • 31,617
3

if using gnu Awk:

awk '{print} /### REPLACE.../{system("cat replacement"); exit 0}' file
JJoao
  • 12,170
  • 1
  • 23
  • 45
3

If you want to edit a file, prefer ed over sed:

ed -s original_file.txt <<'EOF'
/^### REPLACE/+1,$d
r replacement_file.txt
w
EOF

will delete everything after the replace line, insert the contents of the other file, and then save the changes.

Shawn
  • 1,173
  • 6
  • 8
0

Tested and worked fine

Command

sed  -ni -e   '1,/#/p' -e '/#/r replacement_file.txt'  titled original_file.txt

output

common_text
### REPLACE EVERYTHING AFTER THIS LINE ###
testing123
this_is_the_replacement_text