Find and Replace Text in a File Between Range of Lines Using Sed

Find and replace text in a file between range of lines using sed

You can use sed addresses:

sed '19,33s/google/facebook/g' file

This will run the substitution on lines between and including 19 and 33.

The form of a sed command is as follows:

[address[,address]]function[arguments]

Where 19,33 is the addreses,

substitute is function

and global is the argument

How to perform sed replacement on range of lines?

You were close

sed -i '200,220 s/1 2 3 4 5 /replacement numbers/' file

in 200-220 range this will replace '1 2 3 4 5 ' with other stuff only once (per line). If more replacements needed than added g here ...numbers/g' file and so on

Replace text between two lines with contents of a file stored in a variable in sed

This might work for you (GNU sed):

sed '/blue/,/gray/!b;//!d;/blue/r file2' file1

For the range of lines between blue and gray, delete lines that do not match either the first or the last lines in the range and read the lines to insert before the last line of the range.

EDIT:

The first sed command /blue/,/grey/!bmatches a range of lines i.e. the lines that range between a line containing blue upto and including a line containing gray. The !b part means if the lines are not in that range then break out of the sed commands i.e. do not do any further sed processing for these lines, just print as normal.

The sed commands following will only affect those lines that are in the range between blue and gray.

The second command //!d means: delete those lines that do not match either the start/end of the range i.e. blue or gray. The // uses the regexp from a previous /.../ command. N.B. a delete command terminates any further sed processing for that line.

The sed commands following will only affect lines that containing either blue or gray.

The third command matches a line containing blue and reads in lines from file2.

N.B. the lines containing blue and grey are processed by sed naturally and printed before the next line is read into the pattern space as are the lines not between blue and gray.

An alternative:

sed '/blue/,/gray/!b;//!d;/gray/e cat file2' file1

And another:

sed -ne '/blue/{p;r file2' -e ':a;n;/gray/!ba};p' file1

How to replace a range of numbers from a range of strings with sed

You can do everything in one go with a slightly more complex regex.

sed 's/lcl|NC_.*_cds_\(XP_[0-9.]*\)_.*/\1/' cds.fa > cds4.fa

The backslashed parentheses create a capturing group, and \1 in the replacement recalls the first captured group (\2 for the second, etc, if you have more than one). The regex inside the group looks for XP_ followed by digits and dots, and the expression after matches the rest of the line from the next uderscore on.

In other words, this basically says "replace the whole line with just the part we care about".

By the by, there is no reason to backslash underscores anywhere, and the /g option to the s command only makes sense when you want to replace multiple occurrences on the same input line.

Using sed to replace value in lines, between specific line number range in a file

Just add the line numbers in commas

sed "10,13s/Frame=[[:digit:]]\+/Frame=1/" data.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...

Replace a pattern range line by line with sed

The closest code I have gotten is this, but I have to rewrite the
entire range and it is not affordable:

sed -e '/==OPEN==/ {:loop; N; /==CLOSE==/! b loop; /id: class8/ {s/.*/NEEDS REWRITE/}}' /example

That's actually not bad.

If I tell it to rewrite the beginning (^), it rewrites only the first
line of the range, I think it is because it considers the entire
pattern as one line.

Yes, with POSIX sed, and with GNU sed by default, the ^ matches the beginning of the pattern space only. However, you can match the newlines themselves:

sed -e '/==OPEN==/ {:loop; N; /==CLOSE==/! b loop; /id: class8/ {s,\(^\|\n\),\1// ,g}}' \
/example

Note in particular:

  • The text being replaced is expressed as the group \(^\|\n\), meaning either the zero-length substring at the beginning of the pattern space or a newline, which is captured as a group.
  • The matched text is echoed back into the replacement via \1. That has no visible effect when it is the ^ alternative that matches, but it avoids eliminating newlines when the other alternative matches.
  • The comma (,) is used as pattern delimiter, so that the slashes (/) in the replacement text don't need to be escaped.
  • The g flag is used to cause all appearances of the pattern to be replaced, not just the first.

If you are willing to rely on GNU extensions, then you can do it a bit more simply:

sed -e '/==OPEN==/ {:loop; N; /==CLOSE==/! b loop; /id: class8/ {s,^,// ,gm}}' \
/example

With GNU sed, the m flag in the s command causes ^ to match both at the beginning of the pattern space and immediately after each newline within. This flag is not specified by POSIX.

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.



Related Topics



Leave a reply



Submit