JSON 텍스트를 구문 분석하기위한 sed 명령이있는 정규식


15

이 json 텍스트가 있습니다.

{
    "buildStatus" : {
        "status" : "ERROR",
        "conditions" : [{
                "status" : "OK",
                "metricKey" : "bugs"
            }, {
                "status" : "ERROR",
                "metricKey" : "test_success_density"
            }, {
                "status" : "OK",
                "metricKey" : "vulnerabilities"
            }
        ],
        "periods" : []
    }
}

buildStatus의 전체 상태를 추출하려고합니다. 즉 예상 출력이 "ERROR"입니다.

"buildStatus" : {
    "status" : "ERROR",
    ....
}

아래에서 sed 표현식을 시도했지만 작동하지 않습니다 OK.

status= sed -E 's/.*\"buildStatus\":.*\"status\":\"([^\"]*)\",.*/\1/' jsonfile

내가 도대체 ​​뭘 잘못하고있는 겁니까?

답변:


16

JSON 또는 XML과 같은 복잡한 중첩 데이터 구조를 정규식으로 구문 분석하지 말고 적절한 JSON 파서를 사용하십시오 (예 :) jshon.

먼저 설치해야합니다.

sudo apt-get install jshon

그런 다음 표준 입력을 통해 구문 분석 할 JSON 데이터를 제공해야하므로 파이프로 다른 명령의 출력을 |리디렉션하거나 ( ) 파일을 리디렉션 할 수 있습니다 ( < filename).

원하는 데이터를 추출하는 데 필요한 인수는 다음과 같습니다.

jshon -e "buildStatus" -e "status" -u
  • -e "buildStatus" 최상위 사전에서 "buildStatus"색인이있는 요소를 선택합니다.
  • -e "status" 위에서 선택한 두 번째 수준 사전에서 "상태"색인이있는 요소를 선택합니다.
  • -u 선택한 데이터를 JSON에서 일반 데이터로 변환합니다 (예 : 여기에서 문자열 주위의 따옴표를 제거합니다)

따라서 데이터를 가져 오는 위치에 따라 실행하는 명령은 다음 중 하나와 같습니다.

jshon -e "buildStatus" -e "status" -u < YOUR_INPUT_FILE
YOUR_JSON_PRODUCING_COMMAND | jshon -e "buildStatus" -e "status" -u

에 대한 자세한 내용은 여기 를 참조하거나 jshon온라인으로 입력하여 맨 페이지 를 참조 하십시오man jshon .


6
jqjq -r .buildStatus.status
muru


@HTNW 나는 그 대답을 좋아하지 않았다. "단일 XML 오픈 태그"(질문과 같은) 일반적인 언어 이기 때문에 원칙적으로 태그, 주석, cdata와 일치시키기 위해 정규 표현식을 사용하여 완전한 XML 파서를 구축 할 수있다 섹션 및 간단한 스택을 사용하여 중첩 된 컨텍스트 처리). 그러나 JSON에서 가장 '흥미로운'일반 언어는 문자열 리터럴입니다.
Random832

10

직업 jq:

jq -r '.["buildStatus"]["status"]' file.json

단축 할 수 있습니다 :

jq -r '.buildStatus.status' file.json

-r( --raw-output)는 문자열 json형식없이 (즉, 따옴표 없이) 문자열을 출력 합니다.

예:

% cat file.json                   
{
    "buildStatus" : {
        "status" : "ERROR",
        "conditions" : [{
                "status" : "OK",
                "metricKey" : "bugs"
            }, {
                "status" : "ERROR",
                "metricKey" : "test_success_density"
            }, {
                "status" : "OK",
                "metricKey" : "vulnerabilities"
            }
        ],
        "periods" : []
    }
}

% jq -r '.["buildStatus"]["status"]' file.json
ERROR

% jq -r '.buildStatus.status' file.json       
ERROR

아직 설치하지 않은 경우 다음으로 설치하십시오 (Universe 저장소에서 사용 가능).

sudo apt-get install jq 

8

전술 한 바와 같이, 복잡한 구조화 된 데이터를 분석하는 것이 적절한 API를 사용하는 것이 바람직하다. 파이썬은json 모듈이 있습니다.이 스크립트는 개인적으로 스크립트에서 꽤 많이 사용하며 원하는 필드를 추출하는 것은 매우 쉽습니다.

$ python -c 'import sys,json;print json.load(sys.stdin)["buildStatus"]["status"]' <  input.txt
ERROR

여기서 발생하는 일은 입력 파일을 파이썬의 stdin으로 리디렉션하고로 읽습니다 json.load(). 이것은 "buildStatus"키를 가진 파이썬 사전이되고, "status"키를 가진 다른 파이썬 사전을 포함합니다. 따라서 우리는 단지 다른 사전 내에 저장된 사전에 키 값을 인쇄하고 있습니다. 상당히 간단합니다.

단순성 외에도, 다른 장점은 파이썬과이 API가 모두 사전 설치되어 있으며 기본적으로 우분투와 함께 제공된다는 것입니다.


6

당신은 할 수 실제로에서 작업을 수행 sed하지만, 난 강력하게 당신이 JSON 데이터를 처리하기 위해 작성 도구가 더 정교한 언어를 사용하도록 촉구한다. 예를 들어 펄이나 파이썬을 사용해 볼 수 있습니다.

이제 간단한 예제에서 원하는 것은의 첫 번째 항목 "status"이므로 다음과 같이 할 수 있습니다.

$ sed -nE '/status/{s/.*:\s*"(.*)",/\1/p;q}' file.json 
ERROR

트릭을 사용하는 것입니다 -n피할 인쇄에 다음 라인 일치하는 경우 status( /status/), 당신은 모든 것을 제거하지만, 당신이 원하는 부분은 s/.*:\s*"(.*)",/\1/, p선을 RINT 및q UIT을.


개인적 으로이 동등한 grep 명령이 훨씬 간단하다는 것을 알았습니다.

$ grep -m1 -oP '"status"\s*:\s*"\K[^"]+' file.json 
ERROR

또는 이것 :

$ perl -ne 'if(s/.*"status"\s*:\s*"([^"]+).*/$1/){print;exit}' file.json 
ERROR

그러나 JSON 파일을 구문 분석하려는 경우 수동으로 수행하지 마십시오. 적절한 JSON 파서를 사용하십시오.


또는 이것 :grep -m 1 status file.json | tr -cd '[[:alnum:]]:' | cut -f2 -d':'
slowko

1
@ user1876040 천만에요. 답변 중 하나를 수락해야합니다 ( ByteCommander 's 가 더 좋습니다). 질문에 답변 된 것으로 표시 할 수 있습니다.
terdon

6

당신이 말을 안 한다 사용 sed당신이에 뭔가를 검색해야하는 경우,하지만 (나는 누군가가 의무적주의 작성하지 위해 그냥 날을 downvoted 것 같아요) 다음 에 라인 buildStatus, 당신이 말할 필요가 자신의 시도에 시도 할 당신이 보이는대로 sed읽기 N명령을 가진 다음 줄

$ sed -rn '/buildStatus/N;s/.*buildStatus.*\n.*: "(.*)",/\1/p' file
ERROR

노트:

  • -n 요청할 때까지 아무 것도 인쇄하지 마십시오
  • -rERE 사용 (과 동일 -E)
  • /buildStatus/N 이 패턴을 찾아서 다음 줄도 읽어보세요
  • s/old/new/교체 oldnew
  • .* 줄에있는 모든 문자
  • \n 개행
  • : "(.*)",모든 문자 사이에 발생하는 저장 : "",
  • \1 저장된 패턴에 대한 역 참조
  • p 우리가 작업 한 부분을 인쇄

0

이유 sed및 유사한 텍스트 스트림 처리 도구가 JSON 및 XML과 같은 구조화 된 데이터를 구문 분석하는 데 적합하지 않은 이유에 대한 일반적인 설명이 있습니다. 나는 그것을 가지고 있지는 않지만 거기에 있습니다. 그리고 아마도 가장 적은 상황에서 필요한 표현이 빨리 복잡해 지지만 구조를 구문 분석하기 위해 특별히 설계된 대체 도구는 더 복잡하다는 것이 중요합니다 동일한 구문 분석에서 우아하고 읽기 쉽고 효율적입니다.

마찬가지로 muru을 걸었다 코멘트에 , jq작업에 적합한 도구가 될 것이다. 또한 동일한 데이터를 거의 또는 전혀 성공하지 못하도록 파싱하려고 시도한 여러 번 대체되는 것을 개인적으로 매우 기쁘게 생각합니다. 또한 출력 형식을 지정하고 달리 제어 할 수있는 기능이 많이 포함되어 있습니다. 나는 jsontool현재 잊어 버린 이유 이상 을 선호합니다 .

Byte Commander다른 답변jshon 에서 권장 하는 것 같습니다 . 나는 그 도구를 사용하지는 않았지만 나에게 그 구문과 상기 출력에 대한 사용자 정의 가능한 프리젠 테이션을 상기 시켜줍니다 .xmlstarlet



3
jsontoolOP의 특정 사례 에 어떻게 사용될 수 있는지에 대한 예를 보여
주어

Lol @muru, 맞습니다. 이것은 Regex로 XML / JSON 구문 분석에서 사용을 막으려는 게시물 중 하나입니다! 나는 jqmuru와 heemayl이 이미 exmaples를 가지고 있다고 설명하고 그 뒤에 추론을 게시하는 것이 좋습니다 : askubuntu.com/a/863948/230721
Pysis

0

json ( https://github.com/trentm/json ) 이라는 또 다른 Json 도구

$ json buildStatus.status < file.json
ERROR

이 사례 연구는 오해의 소지가 있습니다. 도구가 작동하지 않는 것 같습니다. jsonjson 파일을 변경하는 데 사용할 수도 있습니다 .

$ json -e 'this.buildStatus.status="not error"' < file.json > new.json

또는...

$ json -e 'this.buildStatus.status="no errors"' < file.json | json -e 'this.buildStatus.status
no errors

http://trentm.com/json/의 설명서


설치되지 않은 경우 :

  • 설치 노드
  • 그리고 sudo npm install -g json
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.