Fenomatik
Fenomatik

Reputation: 477

Find and replace in a different line

Lets say I have few lines where I have to select a string within braces and then use it to substitute it elsewhere few lines later

Here is the word that I need to select in braces (WORD)
Second line
Third line
Forth line 
Path where I want it to replace /root/usr/destination/
few more lines

I want to pick WORD and substitute destination with WORD so that it looks like this

Here is the word that I need to select in braces (WORD1)
Second line
Third line
Forth line 
Path where I want it to replace /root/usr/WORD1/
few more lines

Also how can I do this for tis to be recurring in a same file
Here is the word that I need to select in braces (WORD2)
Second line
Third line
Forth line
Path where I want it to replace /root/usr/WORD2/
few more lines

Here is another  word that I need to select in braces (WORD3)
Second set of lines
Third line
Forth line
Path where I want it to replace /root/usr/WORD3/
few more lines and pattern repeats like this so on

Upvotes: 0

Views: 113

Answers (2)

Julio
Julio

Reputation: 5308

By default, sed works line by line. So in order to work with that patter you should make it to work with multiple lines. See this Stackoverflow question.

A simpler alternative would be to use perl. Perl comes with almost any (if not all) linux distros and some UNIX systems.

So you may use this:

perl -0777 -pe 's/([\s\S]*?\()([^)]+)(\)[\s\S]*?\/root\/usr\/)destination([\s\S]*?)/$1$2$3$2$4/g' file.txt

The regex is this one:

([\s\S]*?\()([^)]+)(\)[\s\S]*?\/root\/usr\/)destination([\s\S]*?)

Replace by: $1$2$3$2$4

Demo.

Upvotes: 1

Borodin
Borodin

Reputation: 126722

I'm concerned about your invented input data as it doesn't seem even close to anything that the "answer" in your comment could process correctly. However, here's a solution that reads from the integral DATA file handle. I've read the file a line at a time instead of slurping the whole thing, as it makes it easier to pick up new replacement strings

The only other provisos are that

  • The destination keyword never appears before the replacement word on the same line

  • There is no need to distinguish occurrences of destination that are in a path string

  • There are no parentheses in the input text except for those surrounding the replacement words

use strict;
use warnings 'all';

my $rep;

while ( <DATA> ) {
    $rep = $1 if /\(([^()]+)\)/;
    s/destination/$rep/g if defined $rep;
    print;
}


__DATA__
Here is the word that I need to select in braces (WORD1)
Second line
Third line
Forth line 
Path where I want it to replace /root/usr/destination/
few more lines

Here is the word that I need to select in braces (WORD2)
Second line
Third line
Forth line 
Path where I want it to replace /root/usr/destination/
few more lines

Here is the word that I need to select in braces (WORD3)
Second line
Third line
Forth line 
Path where I want it to replace /root/usr/destination/
few more lines

output

Here is the word that I need to select in braces (WORD1)
Second line
Third line
Forth line
Path where I want it to replace /root/usr/WORD1/
few more lines

Here is the word that I need to select in braces (WORD2)
Second line
Third line
Forth line
Path where I want it to replace /root/usr/WORD2/
few more lines

Here is the word that I need to select in braces (WORD3)
Second line
Third line
Forth line
Path where I want it to replace /root/usr/WORD3/
few more lines

Although I recommend against using them, the one-liner version of this is

perl -pe '$rep = $1 if /\(([^()]+)\)/; s/destination/$rep/g if defined $rep;' myfile

Upvotes: 1

Related Questions