As others have already mentioned in comments, using regular expressions to parse XML is really not a good way to do it. Use an XML processor instead, e.g.
xmlstarlet
is a useful tool for working with XML in shell scripts. Or write your script in a language (e.g.perl
orpython
that have XML processing libraries available. search here on this site and on http://stackoverflow.com/https://stackoverflow.com/ for many examples).Because of 3. and 4. above, the answer to your question is "No, this is not practical because it won't work at all and also because regular expressions shouldn't be used here".
As others have already mentioned in comments, using regular expressions to parse XML is really not a good way to do it. Use an XML processor instead, e.g.
xmlstarlet
is a useful tool for working with XML in shell scripts. Or write your script in a language (e.g.perl
orpython
that have XML processing libraries available. search here on this site and on http://stackoverflow.com/ for many examples).Because of 3. and 4. above, the answer to your question is "No, this is not practical because it won't work at all and also because regular expressions shouldn't be used here".
As others have already mentioned in comments, using regular expressions to parse XML is really not a good way to do it. Use an XML processor instead, e.g.
xmlstarlet
is a useful tool for working with XML in shell scripts. Or write your script in a language (e.g.perl
orpython
that have XML processing libraries available. search here on this site and on https://stackoverflow.com/ for many examples).Because of 3. and 4. above, the answer to your question is "No, this is not practical because it won't work at all and also because regular expressions shouldn't be used here".
#!/bin/bash # get username and password, and remove them from the args U="$1" ; shift P="$2"P="$1" ; shift #edited. was $2 site='website.api.address' element_base='queryResponse/entity' element_AP="${element_base}/accessPointDetailsDTO" element_status="${element_AP}/status" url="https://${U}:${P}@${site}?.devicestatus" for devname in "$@" ; do xml=$(curl -k --silent "${url}&name=${devname}") status=$(printf '%s\n' "$xml" | xmlstarlet sel -t -v "$element_status") echo "$devname: $status" done
#!/bin/bash # get username and password, and remove them from the args U="$1" ; shift P="$2" ; shift site='website.api.address' element_base='queryResponse/entity' element_AP="${element_base}/accessPointDetailsDTO" element_status="${element_AP}/status" url="https://${U}:${P}@${site}?.devicestatus" for devname in "$@" ; do xml=$(curl -k --silent "${url}&name=${devname}") status=$(printf '%s\n' "$xml" | xmlstarlet sel -t -v "$element_status") echo "$devname: $status" done
#!/bin/bash # get username and password, and remove them from the args U="$1" ; shift P="$1" ; shift #edited. was $2 site='website.api.address' element_base='queryResponse/entity' element_AP="${element_base}/accessPointDetailsDTO" element_status="${element_AP}/status" url="https://${U}:${P}@${site}?.devicestatus" for devname in "$@" ; do xml=$(curl -k --silent "${url}&name=${devname}") status=$(printf '%s\n' "$xml" | xmlstarlet sel -t -v "$element_status") echo "$devname: $status" done
First some comments/questions to get you thinking in a different way:
(in other words, this started as a comment but became an actual answer somewhere along the way)
Why are you even trying to extract the
devicename
element when you already know it - it's what you used to fetch the XML (withname=devicename
in the URL)?Even if you didn't already have it, the second
curl
command (with?.devicestatus
) contains bothdevicename
andstatus
elements, so you only need to fetch the second.your
variable1=
andvariable2=
lines are seriously messed up. you've used$grep
rather than$(grep
on both lines and have terminated the double-quote with a:
rather than another double-quote.
i.e. it should be like <<< "$test"
, not <<< "$test:
As others have already mentioned in comments, using regular expressions to parse XML is really not a good way to do it. Use an XML processor instead, e.g.
xmlstarlet
is a useful tool for working with XML in shell scripts. Or write your script in a language (e.g.perl
orpython
that have XML processing libraries available. search here on this site and on http://stackoverflow.com/ for many examples).Because of 3. and 4. above, the answer to your question is "No, this is not practical because it won't work at all and also because regular expressions shouldn't be used here".
Now for some possible solutions:
This just fixes the syntax errors in your script so that it should run:
#!/bin/bash test=$(curl -k --silent "https://username:[email protected]?.full=true&name=devicename") test2=$(curl -k --silent "https://username:[email protected]?.devicestatus&name=devicename") variable1=$(grep -oPm1 "(?<=<name>)[^<]+" <<< "$test1") variable2=$(grep -oPm1 "(?<=<status>)[^<]+" <<< "$test2") echo "$variable" echo "$variable2"
That's far from optimal, though, not least because regular expressions can't reliably parse XML. Trying to do so is an ugly hack at best, and can only work if conditions (i.e. the XML input) are absolutely perfect for what you're trying to extract. Even small changes in the XML output by the server (like eliminating excess spaces, including newlines) can and will break your script.
If I were trying to do what you seem to be doing, here's roughly how I'd do it:
#!/bin/bash U='username' P='password' site='website.api.address' element_base='queryResponse/entity' element_AP="${element_base}/accessPointDetailsDTO" element_status="${element_AP}/status" devname='devicename' url="https://${U}:${P}@${site}?.devicestatus&name=${devname}" xml=$(curl -k --silent "$url") status=$(printf '%s\n' "$xml" | xmlstarlet sel -t -v "$element_status") echo "$devname: $status"
One of the useful things about writing the script this way is that by building up the various strings ($url
and $element_status
in particular) from other variables, it's easy to change them without much risk of typos or other errors. They can also come from the command line (e.g. U="$1" ; P="$2" ; devname="$3"
or using getopts
to process command-line options like -u username -p passsword -d devicename
) or from a config file, or both. You could also provide multiple devname
s on the command line and fetch them in a loop.
Here's another version of the script that combines some of those ideas:
#!/bin/bash # get username and password, and remove them from the args U="$1" ; shift P="$2" ; shift site='website.api.address' element_base='queryResponse/entity' element_AP="${element_base}/accessPointDetailsDTO" element_status="${element_AP}/status" url="https://${U}:${P}@${site}?.devicestatus" for devname in "$@" ; do xml=$(curl -k --silent "${url}&name=${devname}") status=$(printf '%s\n' "$xml" | xmlstarlet sel -t -v "$element_status") echo "$devname: $status" done