0

I am trying to find these two lines:

  <paramsToUseForLimit></paramsToUseForLimit>
</hudson.plugins.throttleconcurrents.ThrottleJobProperty>

and replace them with:

  <paramsToUseForLimit/>
</hudson.plugins.throttleconcurrents.ThrottleJobProperty>
<jenkins.branch.RateLimitBranchProperty_-JobPropertyImpl plugin="branch-api@2.6.3">
  <durationName>hour</durationName>
  <count>2</count>
  <userBoost>false</userBoost>
</jenkins.branch.RateLimitBranchProperty_-JobPropertyImpl>

from my file config.json

Can someone help me to do this with sed ?

sed -ie "s/Those two lines/Replaced with those 7 lines/g" /config.json

  • Thanks for showing your efforts in your question, but this is not clear; could you please post more clear samples of input and expected output in your question for better understanding of your question, thank you. – RavinderSingh13 Mar 24 '21 at 12:19
  • @RavinderSingh13, i have edited the comment – Bogdan-Ionut Raicu Mar 24 '21 at 12:43
  • [This answer](https://stackoverflow.com/a/1732454/4265352) should put you on the right track. – axiac Mar 24 '21 at 13:13
  • Do not use `sed` to parse xml files. Use `xmlstarlet` to insert data in xml. Also `sed` works with _lines_. Doing multiline replces in `sed` is _hard_. It's _not_ the tool for the job – KamilCuk Mar 24 '21 at 13:30
  • the solution that worked for me i found here: https://stackoverflow.com/questions/23234681/adding-xml-element-in-xml-file-using-sed-command-in-shell-script – Bogdan-Ionut Raicu Mar 25 '21 at 07:56

2 Answers2

0

sed may not be the best tool for this task.

sed -ie '/^  <\(paramsToUseForLimit>\)<\/\1/{
  N
  /\n<\/hudson.plugins.throttleconcurrents.ThrottleJobProperty>/{
    i \
  <paramsToUseForLimit/>\
</hudson.plugins.throttleconcurrents.ThrottleJobProperty>\
<jenkins.branch.RateLimitBranchProperty_-JobPropertyImpl plugin="branch-api@2.6.3">\
  <durationName>hour</durationName>\
  <count>2</count>\
  <userBoost>false</userBoost>\
</jenkins.branch.RateLimitBranchProperty_-JobPropertyImpl>
    d
  }
}' /config.json
  • /^.../{ - if pattern space matches first match line:
    • N - append next line of input to pattern space
    • /\n.../{ - if pattern space matches second match line:
      • i \ - insert new text (\ before embedded newlines)
      • d- delete original text, implicit print, and start next cycle
  • otherwise, implicit print (two lines if N ran, else one line)
  • start next cycle

This is quite fragile. For example, watch out for shell metacharacters in the inserted text.

jhnc
  • 11,310
  • 1
  • 9
  • 26
  • 1
    Perhaps the `c` over the `i` command? Both have to use the backslash to continue their input over a newline which points to using a less error fraught technique by using the `r file` having already copied the replacement lines into a second file. e.g. `sed -e '/pattern/{r replacementFile' -e 'd}' inputFile` – potong Mar 24 '21 at 13:34
  • @potong nice! That's much cleaner. Only issue is `pattern` is multiline, so perhaps still need to wrap. – jhnc Mar 24 '21 at 15:34
0

With GNU sed with -z option and inspired with Escape a string for a sed replace pattern question and answer - you can properly escape the patterns and replace newlines with \ n characters and then pass to sed. Then it's simple:

KEYWORD='  <paramsToUseForLimit></paramsToUseForLimit>
</hudson.plugins.throttleconcurrents.ThrottleJobProperty>'
REPLACE='  <paramsToUseForLimit/>
</hudson.plugins.throttleconcurrents.ThrottleJobProperty>
<jenkins.branch.RateLimitBranchProperty_-JobPropertyImpl plugin="branch-api@2.6.3">
  <durationName>hour</durationName>
  <count>2</count>
  <userBoost>false</userBoost>
</jenkins.branch.RateLimitBranchProperty_-JobPropertyImpl>'
ESCAPED_KEYWORD=$(printf '%s\n' "$KEYWORD" | sed -z 's/[]\/$*.^[]/\\&/g; s/\n/\\n/g');
ESCAPED_REPLACE=$(printf '%s\n' "$REPLACE" | sed -z 's/[\/&]/\\&/g; s/\n/\\n/g')
sed -z "s/$ESCAPED_KEYWORD/$ESCAPED_REPLACE/" input_file.txt
KamilCuk
  • 120,984
  • 8
  • 59
  • 111