문자열 조작 쉘 스크립트

문자열 조작 쉘 스크립트

UPS 모니터링 프로젝트에 NUT 서버를 사용하고 있습니다. 내 목표는 명령을 보내고 그에 대한 응답으로 UPS로부터 상태 및 기타 매개변수를 수신하는 쉘 스크립트를 만드는 것입니다.

예를 들어

#!/bin/bash
status='upsc myups' # command to get the status of UPS
sleep 1
exit 0

이것은 나에게 잘 작동하지만 "상태"를 배열로 선언하면 ups의 응답이 단일 요소로 저장됩니다.

#!/bin/bash
declare -a status #declare status as array
# command
status=$(upsc myups)  or status=`upsc myups`
#number of array elements
echo ${status[@]}
exit 0

상태 배열의 요소 수:

1

터미널 출력/어레이 출력

echo ${#status[1]}

배열을 에코하면 출력은 다음과 같습니다.

Init SSL without certificate database
battery.capacity: 9.00 battery.charge: 90 battery.charge.low: 20                                                                 
battery.charge.restart: 0 battery.energysave: no battery.protection: yes  
ups.shutdown: enabled ups.start.auto: yes ups.start.battery: yes   
ups.start.reboot: yes ups.status: OL CHRG ups.test.interval: 604800 
ups.test.result: Done and passed ups.timer.shutdown: -1     
ups.timer.start: -1   
ups.type: offline / line interactive ups.vendorid: 0463

전체 출력이 "상태" 배열의 단일 요소에 저장되기 때문입니다. 모든 매개변수를 개별적으로 로깅하는 데 문제가 있습니다.

원하는 출력:

battery.capacity: 9.00
battery.charge: 90 
battery.charge.low: 20                                                                 
battery.charge.restart: 0
battery.energysave: no 
battery.protection: yes

각 인수를 배열이나 변수의 개별 요소로 분할하는 방법은 무엇입니까?

도와주세요

감사해요

답변1

여기서 반환되는 데이터는 행당 하나 upsc의 형식입니다 . keyword: value이를 통해 sed양식을 가져온 [keyword]="value"다음 이를 사용하여 연관 배열을 초기화할 수 있습니다.

declare -A status="($(upsc myups | sed 's/\(.*\): \(.*\)/ [\1]="\2"/'))"

이제 예를 들어 모든 키워드의 값을 얻을 수 있습니다 echo "${status[device.model]}". 모든 키와 값을 반복하여 원하는 작업을 수행할 수 있습니다.

for key in "${!status[@]}"
do    echo "$key: ${status[$key]}"
done

귀하의 가치를 인용한다면,

status="$(upsc myups)"
echo "${status[@]}"

여전히 값을 얻을 수 있지만 원하는 출력에 표시된 대로 각 값은 새 줄에 표시됩니다.

답변2

다음을 고려할 수 있습니다.

upsc myups | grep -oP 'battery(\.\w+)+: \S+'

주요 요구 사항은 변수를 참조하는 것입니다.

status=$(upsc myups)
echo "$status"

답변3

readarrayBash 내장 명령을 사용할 수 있습니다 .

readarray status < <(upsc myups)

답변4

가장 간단한 해결책은 문자열 대신 배열(예: 괄호로 묶음)을 할당하는 것입니다 $status.

또한 \n각 단어 대신 각 행이 별도의 배열 요소에 배치되도록 IFS를 개행( )으로 설정합니다.

$ IFS=$'\n' status=( $(upsc myups 2>/dev/null | grep '^battery\.') )

$ printf "%s\n" "${status[@]}"
battery.capacity: 9.00
battery.charge: 90
battery.charge.low: 20
battery.charge.restart: 0
battery.energysave: no
battery.protection: yes

$ declare -p status   # reformatted slightly for readability.
declare -a status='([0]="battery.capacity: 9.00" [1]="battery.charge: 90"
                    [2]="battery.charge.low: 20" [3]="battery.charge.restart: 0"
                    [4]="battery.energysave: no" [5]="battery.protection: yes")'

추신: 이 값으로 더 많은 처리를 수행하려면 or 또는 대신을 upsc사용하는 것이 좋습니다 . 둘 다 단독으로 사용하는 것보다 복잡한 텍스트 처리 도구를 작성하는 데 더 적합합니다.perlawkpythonbashbash

관련 정보