나는 지난 며칠간 stackexchange를 뒤져보고 성취하고 싶은 몇 가지 일을 찾았지만, 그것들을 어떻게 하나로 합칠지 잘 모르겠습니다...
API에 대한 컬 호출을 만드는 스크립트를 만들려고 합니다. 그러면 특정 값으로만 구문 분석하려는 XML 묶음이 반환됩니다. 전반적으로 나는 이 스크립트가 호출을 수행하고 값을 구문 분석하고 변수로 설정한 다음 반환(표시)하기를 원합니다.
작업형 솔루션을 찾았을 수도 있지만 그것이 실용적인가요?
#!/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>)[^<]+" <<< "$test:)
variable2=$grep -oPm1 "(?<=<status>)[^<]+" <<< "$test:)
echo "$variable"
echo "$variable2"
[admin]>./script SwitchName UP
이것은 내가 채굴하려는 XML입니다.
<?xml version="1.0" ?>
<queryResponse type="AccessPointDetails" rootUrl="https://website/webacs/api/v1/data" requestUrl="https://website/webacs/api/v1/data/AccessPointDetails?.full=true&name=devicename" responseType="listEntityInstances" count="1" first="0" last="0">
<entity url="https://website/webacs/api/v1/data/AccessPointDetails/14008947223" type="AccessPointDetails" dtoType="accessPointDetailsDTO">
<accessPointDetailsDTO id="14008947223" displayName="14008947223">
<clientCount>6</clientCount>
<clientCount_2_4GHz>0</clientCount_2_4GHz>
<clientCount_5GHz>6</clientCount_5GHz>
<ipAddress>172.16.83.5</ipAddress>
<name>devicename</name>
<unifiedApInfo>
......
</unifiedApInfo>
<upTime>609857</upTime>
</accessPointDetailsDTO>
</entity>
</queryResponse>
<?xml version="1.0" ?>
<queryResponse type="AccessPointDetails" rootUrl="https://website/webacs/api/v1/data" requestUrl="https://website/webacs/api/v1/data/AccessPointDetails?.full=true&name=devicename" responseType="listEntityInstances" count="1" first="0" last="0">
<entity url="https://website/webacs/api/v1/data/AccessPointDetails/14008947223" type="AccessPointDetails" dtoType="accessPointDetailsDTO">
<accessPointDetailsDTO id="14008947223" displayName="14008947223">
<name>devicename</name>
<status>UP</status>
<unifiedApInfo>
......
</unifiedApInfo>
</accessPointDetailsDTO>
</entity>
</queryResponse>
답변1
먼저, 여러분의 생각을 다르게 만드는 데 도움이 되는 몇 가지 의견/질문:
(즉, 댓글로 시작했다가 실제 답변으로 바뀐 것입니다.)
이미 알고 있는 요소를 추출하려고 하는 이유는 무엇입니까 ? ( URL
devicename
에서) XML을 가져오는 데 사용하는 요소는 무엇입니까 ?name=devicename
아직 없어도 두 번째
curl
명령(?.devicestatus
)에는devicename
및status
요소가 포함되어 있으므로 두 번째 명령만 얻으면 됩니다.당신
variable1=
과variable2=
라인이 심각하게 엉망입니다. 두 줄 모두에 not을 사용했으며$grep
다른 큰따옴표 대신 큰따옴표 하나로$(grep
큰따옴표를 종료했습니다 .:
<<< "$test"
즉, 대신에 이렇게 보여야 합니다<<< "$test:
다른 사람들이 이미 주석에서 언급했듯이 정규식을 사용하여 XML을 구문 분석하는 것은 실제로 좋은 접근 방식이 아닙니다.
xmlstarlet
예를 들어, 쉘 스크립트에서 XML을 처리하는 데 유용한 도구인 XML 프로세서를 대신 사용하십시오 . 또는 언어(예perl
:python
사용 가능한 XML 처리 라이브러리가 있는 언어)로 스크립트를 작성합니다. 이 사이트를 검색하고https://stackoverflow.com/많은 예를 들어).위의 3.과 4.로 인해 귀하의 질문에 대한 대답은 "아니요, 전혀 작동하지 않고 여기서 정규식을 사용해서는 안 되기 때문에 실용적이지 않습니다."입니다.
이제 몇 가지 가능한 해결책은 다음과 같습니다.
이는 스크립트의 구문 오류를 수정하여 실행되도록 합니다.
#!/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"
그러나 이는 특히 정규 표현식이 XML을 안정적으로 구문 분석할 수 없기 때문에 최적과는 거리가 멀습니다. 이를 시도하는 것은 기껏해야 추악한 해킹이며 조건(예: XML 입력)이 추출하려는 항목에 완전히 완벽한 경우에만 작동합니다. 서버에서 XML 출력을 조금만 변경해도(예: 줄 바꿈을 포함한 추가 공백 제거) 스크립트가 손상될 수 있습니다.
내가 당신이 하고 있는 일을 하려고 한다면 대략 다음과 같이 할 것입니다.
#!/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"
이러한 방식으로 스크립트를 작성할 때 유용한 점 중 하나는 다른 변수에서 다양한 문자열( $url
특히 $element_status
)을 작성함으로써 오타나 기타 오류의 위험 없이 쉽게 변경할 수 있다는 것입니다. 명령줄(예 : 와 같은 명령줄 옵션 처리 U="$1" ; P="$2" ; devname="$3"
를 위해 )이나 구성 파일 또는 둘 다에서 가져올 수도 있습니다. 명령줄에 여러 를 제공하고 이를 루프로 가져올 수도 있습니다 .getopts
-u username -p passsword -d devicename
devname
다음은 이러한 아이디어 중 일부를 결합한 또 다른 버전의 스크립트입니다.
#!/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