kbar
kbar

Reputation: 77

Globally matching and replacing multi-line text

I am working on a project with many files (100+).

I have two FE properties on every page that I'd like to update. For example,

                property1: {
                    type: String,
                    notify: true,
                    value: "PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "PropTwo"
                },

I could grep for "PropOne" and "Prop2" individually, but I'd rather match on the entire property object for more accuracy.

Is there a way to find and update the values using something like GREP?

Edit: Expected output would be:

                property1: {
                    type: String,
                    notify: true,
                    value: "this is new PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "this is new PropTwo"
                },

Upvotes: 0

Views: 43

Answers (3)

potong
potong

Reputation: 58578

This might work for you (GNU sed):

sed -i '/^\s*property.*: {/,/^\s*},/s/"\(.*\)"/"this is the new &"/' file

This matches on a range of lines starting with property and ending with }, and then substitute the string between double quotes with the required replacement (using a back reference if needed).

Upvotes: 0

anubhava
anubhava

Reputation: 786359

Here is another gnu awk solution:

awk -v RS='},' 'NF {
   sub(/value: "[^"]*"/, "\"this is new " ($1=="property1:"?"PropOne":"PropTwo") "\"")
}
{
   ORS=RT
} 1' file

Output:

               property1: {
                    type: String,
                    notify: true,
                    "this is new PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    "this is new PropTwo"
                },

Upvotes: 1

Ed Morton
Ed Morton

Reputation: 204731

$ cat old
                property1: {
                    type: String,
                    notify: true,
                    value: "PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "PropTwo"
                },

$ cat new
                property1: {
                    type: String,
                    notify: true,
                    value: "this is new PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "this is new PropTwo"
                },

.

$ cat file
lines before
the target
                property1: {
                    type: String,
                    notify: true,
                    value: "PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "PropTwo"
                },
lines after
the target

$ awk -v RS='^$' -v ORS= '
    ARGIND==1 { old=$0; next }
    ARGIND==2 { new=$0; next }
    s=index($0,old) { $0=substr($0,1,s-1) new substr($0,s+length(old)) }
    { print }
' old new file
lines before
the target
                property1: {
                    type: String,
                    notify: true,
                    value: "this is new PropOne"
                },
                property2: {
                    type: String,
                    notify: true,
                    value: "this is new PropTwo"
                },
lines after
the target
$

The above uses GNU awk for multi-char RS and ARGIND. A POSIX version isn't hard to come up with if necessary. It uses string comparison and replacement so regexp and/or backreference metacharacters in your files will be treated as literals and so do not need any special consideration (unlike, say, if you were to attempt to use sed or any other regexp-based approach).

Upvotes: 2

Related Questions