Linux 기반 Synology 플랫폼에 다음 문자열이 있고 일부 값을 추출하고 싶습니다.
{"report":"Instantaneous values:<BR>voltage=243.5 Vrms<BR>FFTComponents:<BR>Phase 1:<BR>\tcurrent=0.348 A, activePower=68.461 W, reactivePower=50.175 var, apparentPower=84.879 VA, cosfi=80, quadrant=0, phaseshift=0.0, phaseDiff=0.0<BR>\tFFTComponents:<BR>Phase 2:<BR>\tcurrent=0.076 A, activePower=2.888 W, reactivePower=18.492 var, apparentPower=18.717 VA, cosfi=10, quadrant=0, phaseshift=0.0, phaseDiff=0.0<BR>\tFFTComponents:<BR>Phase 3:<BR>\tcurrent=1.431 A, activePower=299.807 W, reactivePower=177.96 var, apparentPower=348.646 VA, cosfi=85, quadrant=0, phaseshift=0.0, phaseDiff=0.0<BR>\tFFTComponents:<BR><BR><BR>Phase 1, peak active power 5570.098 W at 03/09/2022 14:18:10<BR>Phase 2, peak active power
4562.172 W at 25/09/2022 09:21:45<BR>Phase 3, peak active power 3188.103 W at 07/11/2022 16:35:35<BR>active energy RMS per phase mapping combination<BR>phase mapping 210=372.779 kWh [ 1/1]<BR>phase mapping 12=808.956 kWh [* 1/3]<BR>phase mapping 21=307.154 kWh [
-1/1]<BR>phase mapping 102=321.293 kWh [ -1/2]<BR>phase mapping 120=508.832 kWh [ 1/0]<BR>phase mapping 201=317.701 kWh [
-1/1]<BR><BR>active energy RMS (solar) per phase mapping combination<BR>phase mapping 210=0.0 kWh [ 1/1]<BR>phase mapping 12=0.0 kWh [* 1/3]<BR>phase mapping 21=0.0 kWh [ -1/1]<BR>phase mapping 102=0.0 kWh [ -1/2]<BR>phase mapping 120=0.0 kWh [ 1/0]<BR>phase mapping 201=0.0 kWh [ -1/1]<BR><BR>"}
인터넷에서 몇 가지 코드를 찾았습니다. 코드는 작동하지만 내가 원하는 모든 정보를 제공하지는 않습니다.
https://github.com/apazga/smappee-domoticz-bash/blob/master/smappee_bash_extractor.sh
코드 섹션은 sed
문자열을 찾고 urrent=
해당 문자열 다음에 오는 값을 반환하는 데 사용됩니다.
AMPS=`echo $SMAP |sed -e 's|.*urrent=\(.*\)|\1|' -e 's|\(.\{1,4\}\).*|\1|'`
AMPSL1, AMPSL2, AMPSL3으로 분할하고 싶습니다.
- AMPL1: 전류의 첫 번째 발생을 검색하고 0.348을 반환해야 합니다.
- AMPL2: 두 번째로 나타나는 전류를 검색하고 0.076을 반환해야 합니다.
- AMPL3: 세 번째로 나타나는 전류를 검색하고 1.431을 반환해야 합니다.
마지막 발생을 반환하는 다음 코드를 찾았습니다.
AMPSL3=`echo $SMAP |sed -e '$s|.*urrent=\(.*\)|\1|' -e 's|\(.\{1,4\}\).*|\1|'`
누구든지 나를 도와줄 수 있나요?
답변1
정규식의 문제점은 셀 수 없다는 것입니다. 따라서 추출하려는 각 값에 대해 서로 다른 복잡한 정규식이 필요합니다. 대신에 필요한 값을 분리하기 위해 grep
before를 사용합니다 .sed
$ AMPS=$(echo "$SMAP" | grep -oE 'current=[0-9]+\.[0-9]+' | sed -E 's|current=||')
$ echo "$AMPS"
0.348
0.076
1.431
head
그런 다음 및 의 조합을 사용하여 개별 값을 추출할 수 있습니다 tail
.
$ AMPSL1=$(echo "$AMPS" | head -1)
$ echo $AMPSL1
0.348
$ AMPSL2=$(echo "$AMPS" | tail +2 | head -1)
$ echo $AMPSL2
0.076
$ AMPSL3=$(echo "$AMPS" | tail +3 | head -1)
$ echo $AMPSL3
1.431
또는 terdon이 제안한 것처럼 "사용하면 이중 헤더/꼬리를 피할 수 있습니다 awk
".
$ AMPSL2=$(echo "$AMPS" | awk 'NR==2')
$ echo $AMPSL2
0.076
답변2
GNU가 있는 경우 grep
(임베디드 시스템에는 없을 수도 있음) 다음을 수행할 수 있습니다.
read ampl1 ampl2 ampl3 < <(grep -oP 'current=\K[0-9.]+' <<<"$amps" | tr '\n' ' ' | sed 's/$/\n/' )
이 관용구를 사용하면 프로세스 대체를 사용하여 read var < <(command)
출력을 command
현재 쉘의 변수에 저장할 수 있습니다.var
grep -o
이는 입력에서 일치하는 부분만 인쇄하는 데 사용되며 PCRE 정규 표현식의 경우 "여기서 이전에 일치한 모든 항목을 잊어버립니다"라는 표기법을 -P
제공합니다 . \K
그런 다음 공백을 줄 바꿈으로 변환 tr
하고 후행 줄 바꿈을 추가하여 모든 것이 변수에 저장된 내장 함수 sed
에 전달되도록 준비 해야 합니다. read
출력은 다음과 같습니다
$ read ampl1 ampl2 ampl3 < <(grep -oP 'current=\K[0-9.]+' <<<"$amps" | tr '\n' ' ' | sed 's/$/\n/' )
$ echo "AMPL1: $ampl1 AMPL2: $ampl2 AMPL3: $ampl3"
AMPL1: 0.348 AMPL2: 0.076 AMPL3: 1.431
사용할 수 없는 경우 grep -oP
다음을 수행할 수 있습니다.
$ read ampl1 ampl2 ampl3 < <(perl -007 -ne '@m=(/current=([0-9.]+)/g); print "@m\n"' a)
$ echo "AMPL1: $ampl1 AMPL2: $ampl2 AMPL3: $ampl3"
AMPL1: 0.348 AMPL2: 0.076 AMPL3: 1.431
bash
이 답변에서는 쉘을 사용해야 합니다 . Synology 시스템의 기본 셸은 bash
POSIX 모드에서 실행되는 셸 이므로 <(...)
프로세스 교체( )가 활성화되지 않습니다. 먼저 bash
를 입력 해야 합니다 bash
.
또는 스크립트에서 이러한 명령을 사용하려면 를 사용하십시오 bash scriptName.sh
.