JSON 파일에서 데이터를 추출하는 방법

JSON 파일에서 데이터를 추출하는 방법

나는 내 문제에 대한 해결책을 찾고 있었지만 해결책을 찾지 못했거나 더 나은 표현으로는 내가 찾은 해결책을 얻지 못했습니다. 내 질문은: 저는 Raspberry Pi에서 스마트 홈 제어 소프트웨어를 사용하고 있습니다. 사용pilight-receive, 실외 온도 센서에서 데이터를 캡처할 수 있습니다. pilight-receive의 출력은 다음과 같습니다.

{
        "message": {
                "id": 4095,
                "temperature": 409.5
        },
        "origin": "receiver",
        "protocol": "alecto_wsd17",
        "uuid": "0000-b8-27-eb-0f3db7",
        "repeats": 3
}
{
        "message": {
                "id": 1490,
                "temperature": 25.1,
                "humidity": 40.0,
                "battery": 1
        },
        "origin": "receiver",
        "protocol": "alecto_ws1700",
        "uuid": "0000-b8-27-eb-0f3db7",
        "repeats": 3
}
{
        "message": {
                "id": 2039,
                "temperature": 409.5
        },
        "origin": "receiver",
        "protocol": "alecto_wsd17",
        "uuid": "0000-b8-27-eb-0f3db7",
        "repeats": 4
}

이제 내 질문은 ID가 1490인 메시지에서 온도와 습도를 추출하는 방법입니다. 얼마나 자주 확인하라고 권하시나요? 10분마다 실행되는 cron 작업을 통해 출력을 생성하고 pilight-receive출력 데이터를 추출하여 스마트 홈 제어 API에 푸시하시겠습니까?

답변1

jq셸을 사용하여 json 파일을 처리 할 수 있습니다 .

예를 들어 샘플 json 파일을 다음과 같이 저장한 raul.json후 다음을 실행했습니다.

$ jq .message.temperature raul.json 
409.5
25.1
409.5
$ jq .message.humidity raul.json 
null
40
null

대부분의 Linux 배포판에 대해 사전 패키징될 수 있습니다.

그 자체로 이 작업을 수행하는 방법이 있을 수 있지만 jq한 줄에 두 개의 원하는 값을 얻는 가장 쉬운 방법은 다음을 사용하는 것입니다 xargs.

$ jq 'select(.message.id == 1490) | .message.temperature, .message.humidity' raul.json | xargs
25.1 40

.message.id또는 각 인스턴스를 반복하려는 경우 .message.id출력에 추가하여 사용할 수 있습니다. xargs -n 3세 가지 필드(id, 온도, 습도)가 있다는 것을 알고 있기 때문입니다.

jq '.message.id, .message.temperature, .message.humidity' raul.json | xargs -n 3
4095 409.5 null
1490 25.1 40
2039 409.5 null

그런 다음 awk 또는 다른 방법을 사용하여 이 출력을 사후 처리할 수 있습니다.


마지막으로, Python과 Perl 모두 json 데이터를 구문 분석하고 조작하기 위한 훌륭한 라이브러리를 가지고 있습니다. PHP와 Java를 포함한 다른 여러 언어와 마찬가지로.

답변2

나 같은 고급 기능에 대해 잘 모르고 사전 설치 awk되어 있지 않은 사람들을 위한 jq간단한 해결책은 다음과 같이 여러 기본 명령을 함께 연결하는 것입니다.

grep -A2 '"id": 1490,' stats.json | sed '/1490/d;s/"//g;s/,//;s/\s*//'

값만 얻으려면 or grep대신 사용하는 awk것이 더 쉽습니다 sed.

grep -A2 '"id": 1490,' stats.json | grep -o "[0-9]*\.[0-9]*"

설명을 하자면 이 방법이 나에게는 가장 쉬운 방법인 것 같다.

  • grep -A2JSON에서 찾고 있는 줄과 온도 및 습도가 포함된 다음 두 줄을 가져옵니다 .
  • 파이프는 grep -o로 구분된 숫자만 인쇄합니다 .(첫 번째 1490줄에는 표시되지 않으므로 온도와 습도라는 두 가지 값만 남습니다. 매우 간단합니다. jq제 생각에는 를 사용하는 것보다 훨씬 간단합니다.

답변3

명령줄에서 JSON을 처리하기 위해 제가 선택한 도구는 jq입니다. 그러나 jq가 설치되어 있지 않으면 Perl을 사용해도 됩니다.

# perl -MJSON -e '$/ = undef; my $data = <>; for my $hash (new JSON->incr_parse($data)) { my $msg = $hash->{message}; print "$msg->{temperature} $msg->{humidity}\n" if $msg->{id} == 1490 }' < data.json
25.1 40

답변4

출력은 완전한 JSON이 아닌 JSON 조각 세트입니다. 출력을 전체 JSON으로 다시 정렬하는 경우(예: 출력이 에 있다고 가정 file.json):

echo "[ $(cat file.json | sed -E 's/^}$/},/; $d') }]"

그러면 jtc도구를 사용하여 원하는 것을 쉽게 얻을 수 있습니다(다음 위치에서 사용 가능).https://github.com/ldn-softdev/jtc):

bash $ echo "[ $(cat file.json | sed -E 's/^}$/},/; $d') }]" | jtc -x "[id]:<1490>d [-1]" -y[temperature] -y[humidity] -l
"temperature": 25.1
"humidity": 40.0
bash $ 

위의 예에서 -l라벨을 인쇄할 필요가 없으면 제거하세요.

관련 정보