Using Sed Replace Line in File with Another File

Using sed replace line in file with another file

From @Aaron

sed "s/^.*find.*$/$(cat newline.txt)/" infile.txt

Where find is a unique string in infile.txt that returns a single line, the line is then replaced by newline.txt

how to use sed to replace the specific line/lines in a file with the contents from another file

To replace a range of lines with entire contents of another file:

sed -e '15r file2' -e '15,18d' file1

To replace a single line with entire contents of another file:

sed -e '2{r file2' -e 'd}' file1

If you don't know whether file2 ends in newline or not, you can use the below trick (see What does this mean in Linux sed '$a\' a.txt):

sed '$ a\' file2 | sed -e '3{r /dev/stdin' -e 'd}' file1

The main trick is to use r command to add contents from the other file for the starting line address. And then delete the line(s) to be replaced. The -e option is needed because everything after r will be treated as filename.

Note that these have been tested with GNU sed, I'm not sure if it will vary for other implementations.

See my github repo for more examples, such as matching lines based on regex instead of line numbers.

sed read entire lines from one file and replace lines in another file

If you have GNU sed which supports s///e, you can use the e to call head -n3 file1

I think (w/o yet testing):

sed '2d;3s/.*/head -n3 file1/e' file2

I'll go verify...

Find line in file and replace it with line from another file

Your sed attempt contains several unexplained errors; it's actually hard to see what you are in fact trying to do.

You probably want to do something along the lines of

sed '3!d;s%.*%s/^matching\.string\.here.*/&/%' file2 |
sed -f - -i file1

It's unclear what you hope for the /s to mean; does your sed have a flag with this name?

This creates a sed script from the third line of file2; take out the pipeline to sed -f - to see what the generated script looks like. (If your sed does not allow you to pass in a script on standard input, you will have to write it to a temporary file, and then pass that to the second sed.)

Anyway, this is probably both simpler and more robust using Awk.

awk 'NR==3 && NR==FNR { keep=$0; next }
/^matching\.string\.here/ { $0 = keep } 1' file2 file1

This writes the new content to standard output. If you have GNU Awk, you can explore its -i inplace option; otherwise, you will need to write the result to a file, then move it back to file1.

Copy a content from one file and need to replace in another file using sed

awk

I am not sure how efficient my code will be for your usage.

awk ' /^Key/{q=$2;next} /A|E/{$0=""; next}/^secret/{$2="\""q"\";"}1' $file1 $file2
$ awk ' /^Key/{q=$2;next} /A|E/{$0=""; next}/^secret/{$2="\""q"\";"}1' $file1 $file2
IJKL
MNOP
secret "qvUkD6QaFBA1jYEpynivMoQx+9V71F4+fdn1TIUKPBNny/3zCnjihd1mwxZg==";
MNOP

Here, I am matching any line starting with the Key and secret string and substituting their values.

sed

You will need to create a variable to fetch the key first.

key=$(sed '1,2d;s/Key: //' $file1) or key=$(awk 'NR==3{print $2}' $file1)

$ echo $key
qvUkD6QaFBA1jYEpynivMoQx+9V71F4+fdn1TIUKPBNny/3zCnjihd1mwxZg==

The following code will generate your expected result, but once again, I am not sure how efficient it will be for your usage.

sed "/^secret/s|key|$key|" $file2
$ sed "/^secret/s|key|$key|" $file2
IJKL
MNOP
secret "qvUkD6QaFBA1jYEpynivMoQx+9V71F4+fdn1TIUKPBNny/3zCnjihd1mwxZg==";
MNOP

Replace block of text inside a file using the contents of another file using sed

So I guess this should be a reasonably short way of doing it to replace text between foo and bar lines with content of file file_content:

sed -e '/^foo$/,/^bar$/{/^bar$/{x;r content_file
D};d}' file

For range of lines matching ^foo$ and ^bar$. If line matches ^bar$ swap (empty) hold space into pattern space, read and append content of content_file, then delete pattern space up to first newline and start next cycle with the reminder of the pattern space. For all other lines in that range... just drop the line (delete patter space and move to the next line of input).

Otherwise to the result of your question... any string enclosed in single quotes is taken literally by shell and without any expansion (also of variables) taking place. '${content}' means literally ${content} and that is also part of the argument passed to sed, whereas double quote text ("${content}") would still see shell expand variable to what its value before becoming part of the sed arguments. Since that could still see content tripping up sed, I would opt for the r method for being more generic / robust.


EDIT: Edit keeping the start and end lines in (since I've misread the question):

sed -e '/^foo$/,/^bar$/{/^foo$/{r content_file
p};/^bar$/!d}' file

This time for range between matched of ^foo$ and ^bar$... for opening line matching ^foo$ we it reads content from content_file appending it to pattern space and then prints it (because of delete that follow). Then for all line in the range not matching the closing line pattern ^bar$ it just drops it and moves on.

Replace whole line containing a string using Sed

You can use the change command to replace the entire line, and the -i flag to make the changes in-place. For example, using GNU sed:

sed -i '/TEXT_TO_BE_REPLACED/c\This line is removed by the admin.' /tmp/foo

Using sed to copy one line to another

This might work for you (GNU sed):

sed -Ei  '4{:a;N;6!ba;s/^[^\n]*(\n.*\n(.*))/\2\1/}' file1 file2 file3 fileetc

Gather up lines between line 4 and 6 and then replace line 4 by line 6.


Alternative:

sed '4d;5,6{H;5h;6!d;G}' file

Delete line 4 (not needed).

In the range between lines 5 and 6, append a copy of line 6 to a copy of line 5 and append those copies to line 6.



Related Topics



Leave a reply



Submit