-1

I currently have a build.gradle which looks like this:

buildscript {
    repositories {
        jcenter()
        maven {
            url "https://maven.google.com"
        }
    }
}

allprojects {
    repositories {
        jcenter()
        maven {
            url "https://maven.google.com"
        }
    }
}

it should look like this:

buildscript {
    repositories {
        google()
        jcenter()
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

To be specific I need to replace

jcenter()
maven {
   url "https://maven.google.com"
}

with

google()
jcenter()

I have to do this on the fly, f. ex. with sed as the build.gradle is generated by cordova on the build. Some packages are not found in jcenter. That's why I have to change the order.

I was able to replace the first three lines:

sed -i '' -e 's#jcenter()#google()#g' build.gradle
sed -i '' -e 's#maven {#jcenter()#g' build.gradle
sed -i '' -e 's#url "https:\/\/maven.google.com"##g' build.gradle

Now the repositories part of my build.gradle looks like this:

google()
jcenter()

}

there is a leftover }. How can I remove the leftover } without removing every other closing bracket?

Or is there a better solution than replacing line by line with sed? I have started with sed, but I'm open to any other tool that gets the job done. It should run in a centos container.

mles
  • 4,534
  • 10
  • 54
  • 94
  • Your regular expressions looks for all the text on a single line, but it's on multiple lines, so there is no match. Matching multi-line expressions in `sed` is challenging. Are you positive you cannot use e.g. Perl or Awk instead? – tripleee Jun 11 '18 at 10:19
  • @Micha Those are not available in `sed` – tripleee Jun 11 '18 at 10:20
  • More possible duplicates https://stackoverflow.com/questions/8164604/replacing-multiple-line-pattern-in-sed https://stackoverflow.com/questions/37801921/how-to-use-sed-to-replace-multiline-string etc – tripleee Jun 11 '18 at 10:25
  • Yeah, [that answer](https://stackoverflow.com/a/38147141/3832970) should help. Just make sure you use 2 `N`s since you need to read in 2 lines. Use [this code](http://rextester.com/EZVM93611). – Wiktor Stribiżew Jun 11 '18 at 10:31
  • 1
    While this question may be similar, none of the answers to the question it was closed as a duplicate of are reasonable since they're all convoluted sed hieroglyphics and the right answer would be a clear, simple awk script so IMHO this should not have been closed as a duplicate so I've reopened it. – Ed Morton Jun 11 '18 at 10:50

1 Answers1

1

sed is for simple substitutions on individual lines, s/old/new/, that is all. This will work efficiently using any awk in any shell on any UNIX box and will be absolutely trivial to change if/when your requirements change:

$ awk '{s=$0} sub(/jcenter/,"google"){print $0 ORS s; f=1} !f{print} /}/{f=0}' file
buildscript {
    repositories {
        google()
        jcenter()
    }
}

allprojects {
    repositories {
        google()
        jcenter()
    }
}

If you want to change the original file then if you're using GNU awk just add -i inplace at the front, with other awks just add > tmp && mv tmp file at the end.

The above does the following:

{s=$0}                    # save the current record (a line in this case)
sub(/jcenter/,"google") { # IF jcenter exists THEN replace it with google and
    print $0 ORS s;       #   print the new google line followed by the original jcenter line
    f=1                   #   and set a flag to say you "found" jcenter
}
!f{print}                 # if the flag is not set then print the current line
/}/{f=0}                  # when a "}" is found clear the flag.
Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • Where does this code check for `maven`? Does it remove anything after `jcenter`? Then it may "overmatch". – Wiktor Stribiżew Jun 11 '18 at 11:15
  • It doesn't check for maven as there's no indication in the question that it has to. There's lots of possibilities for things that COULD be different from what the OP has posted (what if all the text is on a single line? What if jcenter appears multiple times? What if it appears in a comment? etc. etc) but it's best to assume that what is posted is adequately representative of the real data and let the OP tell us and update his example if the current example isn't adequate. – Ed Morton Jun 11 '18 at 11:38
  • It is not true *there's no indication in the question*. OP uses `maven { url "https://maven.google.com" }` pattern to actually get the text with `maven` in it hence my comment. If an answer is based on specific assumptions, it is a good idea to add them to the answer. – Wiktor Stribiżew Jun 11 '18 at 11:42
  • That just means the OP is trying to piece together a script using sed. He's already changing the data solely based on finding jcenter (`sed -i '' -e 's#jcenter()#google()#g' build.gradle`) so the posted scripts together do not indicate that we additionally require a test on `maven` to make changes. The answer is just based on the assumption that the OP wants to get the posted output from the posted input. – Ed Morton Jun 11 '18 at 11:44
  • Hi, thanks for reopening my question. I've updated my question to be more specific – mles Jun 11 '18 at 12:32
  • You're welcome. So my script does exactly what you wanted then, right? If not then please edit your question to include in your sample input/output any cases where my script would fail. – Ed Morton Jun 11 '18 at 12:48
  • 1
    Yes it did. Sorry for the late reply. The last time I used awk was like six years ago. Can you elaborate a bit what your awk expression is doing? – mles Jun 13 '18 at 23:15
  • 1
    OK, I added an explanation to my answer. Let me know if you have any questions. – Ed Morton Jun 13 '18 at 23:22