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:2番目に現れる電流を検索し、0.076を返す必要があります。
- AMPL3:3番目に現れる電流を検索し、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
。