2

I have a text file called branch.txt:

$ cat branch.txt
DEMAND_NAME-CR-1234
DEMAND_NAME-CR-8970

Using the above branch name, I have to find and replace some values using a sed command:

branch_name=`(cat /tmp/branch.txt)`
sed -i "s/deploy_branch/$branch_name/g" /tmp/input.file

When I run the sed command, I get an error like the one below:

sed: -e expression #1, char 35: unterminated `s' command

Expected output:

<Project description="first-deployment" name="DEMAND_NAME-CR-1234 DEMAND_NAME-CR-8970 " overwrite="true" type="Repository">
      </Project>

Input file:

<Project description="first-deployment" name="deploy_branch" overwrite="true" type="Repository">
      </Project>
Kusalananda
  • 333,661
viswa
  • 23

1 Answers1

2

The issue with your sed command is that $branch_name contains an embedded newline character. This breaks the syntax of the substitution command in sed when you inject it into the sed editing expression.


Using xmlstarlet to update the name attribute of the document's Project root node to be the contents of the branch.txt file with each newline replaced by a space:

xmlstarlet edit \
    --update '/Project/@name' \
    --value "$(paste -s -d ' ' branch.txt)" input.file

or, shorter,

xmlstarlet ed \
    -u '/Project/@name' \
    -v "$(paste -s -d ' ' branch.txt)" input.file

The paste command in the command substitution reads the branch.txt file and replaces each newline, apart from the last, with a space character. This results in a string used as the new value for the name attribute. If you want to retain the final newline character and convert it into a trailing space (as in your expected output), then use tr '\n' ' ' <branch.txt in place of the paste command.

The xmlstarlet utility is invoked with its ed sub-command. This command edits an XML file, and we specify that we'd like to update a particular element via an XPath query matching the attribute.

Would you need to make the change only when the name attribute's value is deploy_branch, then use the XPath query /Project/@name[. = "deploy_branch"] or /Project[@name = "deploy_branch"]/@name instead.

The output of the above commands would be

<?xml version="1.0"?>
<Project description="first-deployment" name="DEMAND_NAME-CR-1234 DEMAND_NAME-CR-8970" overwrite="true" type="Repository">
      </Project>

The xmlstarlet tool can be made to make an in-place edit if you give it the --inplace (-L) option after ed or edit. You may avoid having the <?xml ...> declaration added by using --omit-decl (-O).

Kusalananda
  • 333,661
  • Thanks for the update, i will try install xmlstarlet in my linux box then i will add above content in my azure pipeline – viswa Oct 07 '22 at 14:15
  • Hi @Kusalananda, above xmlstarlet command can able edit the file but not able save the content which is exist in branch.txt – viswa Oct 07 '22 at 17:11
  • can you please help me – viswa Oct 07 '22 at 17:11
  • @viswa Sorry, I don't understand. If you want to save the modified data back to the same filename, use xmlstarlet ed --inline followed by the rest of the command (I mentioned this in the last paragraph of my answer). – Kusalananda Oct 07 '22 at 17:15