0

I have a long javascript file long.js which has this content as a part of it

... more lines

ProcessCoverageController.createExampleQueries = function () {
    return [
        {
            title: '-- Select a query --',
            query: ''
        }, {
            title: 'No encoding',
            query: 'return avg($c)'
        }
    ];
};
ProcessCoverageController.$inject = [
    "$scope",
    "$log",
    "$interval",
    "Notification",
    "rasdaman.WCSService",
    "rasdaman.ErrorHandlingService"
];

... more lines

What I want to do is to replace the content of return [ ... ]; with the content from another file (e.g: content.js) which has this content:

return [
        {
            title: 'title1',
            query: `query1 as asdasd asdasd`
        }, {
            title: 'title2',
            query: `query2 asdas dasd asd asda`
        }, {
            title: 'title3',
            query: `query3 asd asdasdasdasdasdasdasd`
        }, {
            title: 'title4',
            query: `query4 3asd asdasda sdasdasdasdasdad`
        }
    ];

Can someone give me a hint how to do that with sed or perl (I've tried to look at that, and it seems perl is an easier tool to do then sed). This example below doesn't work properly though:

#!/bin/bash

file_content=`cat content.js`
perl -i -p0e 's/ProcessCoverageController.createExampleQueries = function.*?ProcessCoverageController.\$inject/$file_content/s' long.js
0

2 Answers 2

3

The problem can be solved in a multitude of ways, some being shown below.

Note: /BEGIN/ /END/ I have chosen so that they stand out clearly. Replace them with your required boundary markers.

sed The assumption is that /END/ shud not occur on the last line.

sed -e '
  /BEGIN/,/END/!b
  //!d;/END/!b
  r content.js
  N
' long.js

Working:

  • print any non block region as is: /BEGIN/,/END/!b
  • Within a block, delete the cavity: //!d
  • Print the top boundary of the block: /END/!b
  • Populate the output buffer with the contents of the content.js file: r contents.js No printing to stdout is done here.
  • Read the next line and append to the /END/ line. The act of reading triggers the flushing of the output buffer. Note, due to the N command, the pattern space is not printed in that cycle. This has the effect of placing the contents of content.js file before the /END/ line.

awk '
  BEGIN {
    repl = ARGV[1]
    ARGV[1] = ""
  }
  /BEGIN/ && !f {print;f=1}
  /END/ && f {
    while (getline t < repl > 0) {
      print t
    }
    f = 0
  }
  !f
' content.js long.js

perl -pe '
  $repl //= do{local $/;<STDIN>;};
  next unless my $e = /BEGIN/.../END/;
  $_ = $e =~ /E0/ ? $repl.$_
     : $e == 1 ? $_
     : s/.*//sr;
' long.js < content.js

contnt=$(< "content.js" sed -e 's/^/ /')

cat - <<eof | ed -s - long.js
1m1
/BEGIN/+1,/END/-1c
$contnt
.
?BEGIN?+1,/END/-1s/^ //
wq
eof
0

I found a way using sed from this useful answer https://stackoverflow.com/a/49511949/2028440

sed -e '/ProcessCoverageController.createExampleQueries =/,/ProcessCoverageController.$inject/!b' -e '/ProcessCoverageController.$inject/!d;r content.js' -e 'd' long.js

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .