Replace value across multiple lines in bash

Related searches

I'm struggling even with all the examples available on stackoverflow and google.

Basically i have the following text

    /start r.start ""
      GAIN 0x256 __POSITIVE 1 FOO
      OTHER
      OTHER
      /start MACRO
        200
        CODE "r.start" 0x256 0x2 10 0xA3
      /end MACRO
      OTHER
    /end

and i need to read through this file searching for a name e.g. r.start which is passed as $1 and substitute e.g. 0x256 with a value that i pass as $2. There a two instance to substitute, line 2 and line 7.

Things i know:

  1. /start is preceded by 4 spaces
  2. GAIN is preceded by 6 spaces
  3. \r\n or \n might be present
  4. CODE is preceded by 8 spaces

Till now i've reached this point

pattern="N;s\s\/start r.start \"\"\n      GAIN 0x\(.*\)"
replacement"\/start r.start \"\"\n      GAIN 0x82"
sed -e "$pattern/$replacement/p" test.txt

but i get nothing. I was also able to substitute the first line but for whatever reason it pasted me the first two lines twice on top of each other

the expected value assuming the following call

./run.sh r.start 0x284569

should be

    /start r.start ""
      GAIN 0x284569 __POSITIVE 1 FOO
      OTHER
      OTHER
      /start MACRO
        200
        CODE "r.start" 0x284569 0x2 10 0xA3
      /end MACRO
      OTHER
    /end

Here's my best shot for the second part

var="r.start"
val="0x48209F82"

pattern="\(CODE \"$var\" \).*\(.*\)"
replacement="\1$val\2"
sed "s/$pattern/$replacement/g" test.txt

The problem is that it is deleting everything after the value substitution. I can't put in \2 the following chars

EDIT:

By doing the following

var="r.start"
val="0x48209F82"

pattern="\(CODE \"$var\" \).*\(\s.*\s.*\s.*\)"
replacement="\1$val\2"
sed "s/$pattern/$replacement/g" test.txt

I get what i want but it feels a little bit dirty, how do i reduce the last part in case of a variable number of char? Can i just somehow match everything till end of line?


Replace multiline string in files, Substitute "Some\nThing" by the contents of file "new" in one or more input files perl -i -p0e 's/Some.*?thing\n/`cat new`/se' input.txt -i to change input.txt� -pi -e is your standard "replace in place" command-line sequence, and -0777 causes perl to slurp files whole. See perldoc perlrun to find out more about it.


This might work for you (GNU sed):

sed -E '/^    \/start r\.start /{:a;N;/^    \/end$/M!ba;s/^(      GAIN |        CODE "r\.start" )0x\S+/\10x284569/Mg}' file

Gather up lines between /start and /end and using pattern matching replace the desired values.

The solution may be placed in a function:

f () { sed -E '/^    \/start '"$1"' /{:a;N;/^    \/end$/M!ba;s/^(      GAIN |        CODE "'"$1"'" )0x\S+/\1'"$2"'/Mg}' "$3"; }

And called:

f r\\.start 0x284569 file

SED replace across multiple lines, sed reads each line in turn, so it'll never match a multiline pattern unless you nudge it in the right direction. The N command reads one line from� Assuming that you want to search for the string search through multiple files and replace it with replace, this is the one-liner: grep -RiIl 'search' | xargs sed -i 's/search/replace/g'. Let me now dissect it and take a quick look at the different tools in use.


Here is a perl way:

#!/usr/bin/perl 
use strict;
use warnings;

# retrieve the 2 parameters
my $start = shift @ARGV or die "missing 1rst arg";
my $repl =  shift @ARGV or die "missing 2nd arg";

# input file
open my $fh_in, '<', 'file.txt' or die "$!";
# output file
open my $fh_out, '>', 'output' or die "$!";

# loop through input file
while(<$fh_in>) {
    # if we are between /start {1srt parameter} and /end
    if (/^ {4}\/start\h+$start/ ... /^ {4}\/end\h*$/) {
        # substitute 0x.... by {2nd parameter}
        s/^(?: {6}GAIN | {8}CODE "$start" )\K0x\w+/$repl/;
    }
    print $fh_out $_;
}

In action:

cat file.txt 
    /start other.start ""
      GAIN 0x256 __POSITIVE 1 FOO
      OTHER
      OTHER
      /start MACRO
        200
        CODE "r.start" 0x256 0x2 10 0xA3
      /end MACRO
      OTHER
    /end
    /start r.start ""
      GAIN 0x256 __POSITIVE 1 FOO
      OTHER
      OTHER
      /start MACRO
        200
        CODE "r.start" 0x256 0x2 10 0xA3
      /end MACRO
      OTHER
    /end

./test.pl r.start 0x123456

cat output 
    /start other.start ""
      GAIN 0x256 __POSITIVE 1 FOO
      OTHER
      OTHER
      /start MACRO
        200
        CODE "r.start" 0x256 0x2 10 0xA3
      /end MACRO
      OTHER
    /end
    /start r.start ""
      GAIN 0x123456 __POSITIVE 1 FOO
      OTHER
      OTHER
      /start MACRO
        200
        CODE "r.start" 0x123456 0x2 10 0xA3
      /end MACRO
      OTHER
    /end

text processing, This can be done very easily in perl : $ perl -i -p0e 's/START.*?END/ SINGLEWORD/s' file $ cat file My block of line starts from here� The author is the creator of nixCraft and a seasoned sysadmin, DevOps engineer, and a trainer for the Linux operating system/Unix shell scripting. Get the latest tutorials on SysAdmin, Linux/Unix and open source topics via RSS/XML feed or weekly email newsletter.


You want sed for this, and don't need a script:

Assuming the text is a file called the_text:

sed "s/0x256/REPLACETEXT/g" the_text

If you ant to do that with out echoing out the text then add a -i

sed -i "s/0x256/REPLACETEXT/g" the_text

It is possible to daisy chain these commands or embed them into single script, this one echoes to the standard out:

#!/bin/bash

sed "s/0x256/${2}/g" $1
sed "s/0x256/${2}/g" $1

Replace a line with multiple lines in a file, Linux replace multiple lines in file. Replace multiline string in files, Substitute " Some\nThing" by the contents of file "new" in one or more input files perl -i -p0e� with recent bash shell, and assuming you do not need to traverse directories for file in *.txt do while read -r line do echo $ {line//find/replace} > temp done <"file" mv temp "$file" done


Replace multiple lines between tags using sed, But unfortunately, the command failed to replace as i want, it only work if the content between the tags are not break into multi-line. Could someone please� An unique marker (in this case ) is prepended to the start of the line and used as a method to bump-along the search throughout the length of the line. Once the marker reaches the end of the line the process is finished and is printed out the lookup table and markers being discarded. N.B.


For example to search all 3 digit numbers and replace them with the string number you would use: sed -i 's/\b[0-9]\{3\}\b/number/g' file.txt number Foo foo foo foo /bin/bash demo foobar number Another useful feature of sed is that you can use the ampersand character & which corresponds to the matched pattern. The character can be used multiple


sed -i 's/word1/word2/g' input.file. sed -i -e 's/word1/word2/g' -e 's/xx/yy/g' input.file. ## use + separator instead of / ##. sed -i 's+regex+new-text+g' file.txt. The above replace all occurrences of characters in word1 in the pattern space with the corresponding characters from word2.