Home > Software design >  Replace the first 2 lines containing a string with a specific line with a bash script
Replace the first 2 lines containing a string with a specific line with a bash script

Time:02-10

I need to replace the first 2 occurrences of:

"<version>*" 

with

"<version>$NEW_VERSION</version>"

within an already existing xml file.

Original:

<groupId>my.test.group</groupId>
<artifactId>maven-parent</artifactId>
<version>1.3.0-SNAPSHOT</version>
<version>1.3.0-SNAPSHOT</version>

Desired result:

<groupId>my.test.group</groupId>
<artifactId>maven-parent</artifactId>
<version>1.3.1-SNAPSHOT</version>
<version>1.3.1-SNAPSHOT</version>

I've tried for a while now and this:

sed -i -e '0,/<version>*/s/<version>*/<version>1.3.1-SNAPSHOT<\/version>/' pom.xml

gets close, but the resulting string is:

<groupId>my.test.group</groupId>
<artifactId>maven-parent</artifactId>
<version>1.3.1-SNAPSHOT</version>1.3.0-SNAPSHOT</version>

CodePudding user response:

With awk:

$ awk -v new_version="1.3.1-SNAPSHOT" 'BEGIN {matches = 0} /^<version>/ && matches < 2 {print "<version>" new_version "</version>"; matches  ; next} 1' pom.xml
<groupId>my.test.group</groupId>
<artifactId>maven-parent</artifactId>
<version>1.3.1-SNAPSHOT</version>
<version>1.3.1-SNAPSHOT</version>

If you have whitespaces before <version> lines like that:

<groupId>my.test.group</groupId>
<artifactId>maven-parent</artifactId>
      <version>1.3.0-SNAPSHOT</version>
   <version>1.3.0-SNAPSHOT</version>
 <version>1.3.0-SNAPSHOT</version>

and you want to save them:

$ awk -v new_version="1.3.1-SNAPSHOT" 'BEGIN {matches = 0} /^( *)<version>/ && matches < 2 { match($0, "^ *"); print substr($0, RSTART, RLENGTH) "<version>" new_version "</version>"; matches  ; next} 1' pom.xml
<groupId>my.test.group</groupId>
<artifactId>maven-parent</artifactId>
      <version>1.3.1-SNAPSHOT</version>
   <version>1.3.1-SNAPSHOT</version>
 <version>1.3.0-SNAPSHOT</version>

CodePudding user response:

This might work for you (GNU sed):

sed -E '/<version>/{x;s/^/x/;/xx{2}/!{x;s/(<version>)[^<]*/\1NEW VERSION/;x};x}' file

Match <version> on any line,swap to the hold space, increment a counter and if that counter exceeds the required number of overall substitutions, continue with no further processing.

Otherwise, swap back to the pattern space and substitute the new version.

  • Related