0

I have an xml file that consists of strings

<server name="srv-usr--crt-Internal.vcdn--lfagent1">

and

<server name="srv-usr--crt-Internal.vcdn--lfagent2">
                                          ^^^^^^^^

I want to run a bash script, which continuously executes the xml file by changing the value in the server name i.e for the first time the values will be lfagent1 and lfagent2, the xml file is executed and then the value changes to lfagent3 and lfagent4. There should be around 500 to 1000 such iterations.

How to write a bash script for this test?

12
  • What do you mean by 'executing an xml file'? Commented Feb 13, 2015 at 16:46
  • It would be helpful if we knew how to separately address the two server entries within the file -- if there's a different XPath path to each. Commented Feb 13, 2015 at 16:46
  • What's the point of changing it continuously? Why not change it to the final result after all the iterations? Commented Feb 13, 2015 at 16:46
  • @Barmar, ...I'm presuming that some other piece of test code is being run between each iteration. Commented Feb 13, 2015 at 16:47
  • An option might be to copy/paste the original file into as many clones as needed, replacing the lfagent string underway, finally cat-ting the files and 'executing' (whatever the meaning) the result. Commented Feb 13, 2015 at 16:49

2 Answers 2

1

Use proper XML tools for processing XML. For example, xsh:

open file.xml ;
for //server {
    my $x = xsh:match(@name, '^(srv-usr--crt-Internal.vcdn--lfagent)([0-9]+)$') ;
    if (2 = count($x))
        set @name concat($x[1], 2+$x[2]) ;
}
save :b ;
Sign up to request clarification or add additional context in comments.

Comments

1

This answer uses XMLStarlet for parsing and updating XML safely.

The first job is extracting the content:

filename="input.xml"
IFS=$'\n' read -r -d '' -a old_names \
  < <(xmlstarlet sel -t -m '//server/@name' -v . -n <"$filename")

Next, generating the new values. Assuming that the only numbers that exist in any name are at the end:

new_names=( )
for name in "${old_names[@]}"; do
  name_prefix=${name%%[0-9]*}
  old_number=${name#$name_prefix}
  new_number=$(( old_number + ${#old_names[@]} ))
  new_names+=( "${name_prefix}${new_number}" )
done

Finally, generating and running a command to update the XML file:

update_command=( xmlstarlet ed )
for idx in ${!new_names[@]}; do
  update_command+=(
    -u "//server[$((idx + 1))]/@name" # XPath uses 1-indexed values
    -v "${new_names[$idx]}"           # ...whereas bash arrays are 0-indexed
  )
done
tempfile=$(mktemp "$filename.XXXXXX")
"${update_command[@]}" <"$filename" >"$tempfile" && mv "$tempfile" "$filename"

1 Comment

This has actually been tested end-to-end now. Apologies about the buggy first iteration.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.