Como grep / print valor de uma chave no json que é armazenado em uma variável?

1

Eu tenho uma variável com json aninhado,

a={"content":[{"JOB_STATUS_ID":283739,"PROGRAM_ID":57,"STATUS":"Completed","**DATA_DATE**":"2017-03-09 00:00:00","**START_TIME**":"2017-03-10 00:46:13","END_TIME":"2017-03-10 00:56:40","TOTAL_ROWS":null,"UPDATED_ROWS":null,"DELETED_ROWS":null,"INSERTED_ROWS":null,"REF1":"NULL","REF2":"NULL","AUD_CREATE_DT":"2017-03-10 00:46:13","AUD_CREATE_USER":"JOB_CONTROL","AUD_MODIFY_DT":"2017-03-10 00:56:40","AUD_MODIFY_USER":"JOB_CONTROL"},

{"JOB_STATUS_ID":109711,"PROGRAM_ID":57,"STATUS":"Completed","DATA_DATE":"2017-01-11 00:00:00","START_TIME":"2017-01-12 16:55:14","END_TIME":"2017-01-12 18:54:51","TOTAL_ROWS":null,"UPDATED_ROWS":null,"DELETED_ROWS":null,"INSERTED_ROWS":null,"REF1":"NULL","REF2":"NULL","AUD_CREATE_DT":"2017-01-12 16:55:14","AUD_CREATE_USER":"JOB_CONTROL","AUD_MODIFY_DT":"2017-01-12}

Procurando por uma forma de fazer o grep DATA_DATE e START_TIME do primeiro json no json aninhado (como o que está destacado) na variável a.

Alguma ajuda?

Pronto para usar o awk, sed ou scripts de shell.

    
por Nick 18.07.2017 / 16:23

4 respostas

2

Use jq :

$ echo $a | jq '.[][0]["**DATA_DATE**"]'
"2017-03-09 00:00:00"

Como o jq pode não estar disponível para todas as distros e você pode não querer compilar você mesmo, você pode tirar proveito de muitas outras linguagens de script que possuem suporte ao JSON em suas bibliotecas básicas.

Perl:

$ perl -e "use JSON::Parse 'parse_json'; my \$a = parse_json ('$(echo $a)'); print \$a->{'content'}[0]{'**DATA_DATE**'}"
2017-03-09 00:00:00

Python:

$ python -c "import json; a=json.loads('$(echo $a)'); print(a['content'][0]['**DATA_DATE**'])"
2017-03-09 00:00:00

Ruby:

$ ruby -e "require 'json'; puts JSON.parse('$a')['content'][0]['**DATA_DATE**'];"
2017-03-09 00:00:00

É claro que você pode (ab) usar as ferramentas padrão * nix (GNU) para obter seus valores deste exemplo JSON específico, mas isso não é conveniente. Você pode pegar a primeira linha Depois que a estrutura JSON mudar, seu código se comportará de forma imprevisível.

    
por 18.07.2017 / 17:40
1

Para JSON, você usa uma ferramenta que entende JSON, por exemplo jq e não o awk / sed:

$ echo $a | jq '.content[0].DATA_DATE'
"2017-03-09 00:00:00"

Similarmente para START_TIME . Para a maioria das distros, jq está disponível como um pacote.

    
por 18.07.2017 / 16:36
1

Eu sou um fã de usar looklounds Perl para esse tipo de coisa

echo $a | grep -oP '(?<=DATE**:).*?(?=,)'

e

echo $a | grep -oP '(?<=START_TIME**:).*?(?=,)'

    
por 18.07.2017 / 17:40
0

Como outros já disseram, é muito melhor usar uma linguagem (como perl, python ou ruby) que tenha bibliotecas para analisar json, ou uma ferramenta de propósito especial que o faça como jq ... mas se você realmente quer ou precisa processar dados do json com ferramentas comuns como awk ou sed , então primeiro você precisa convertê-lo em um formato orientado a linhas.

Por quê? Porque você não pode analisar com segurança o json apenas com expressões regulares, e mesmo que você ache que teve sucesso, o que tem será incrivelmente frágil e propenso a romper com mudanças até triviais na entrada esperada.

jsonpipe (escrito em python) é uma dessas ferramentas que pode realizar a conversão para o formato orientado a linhas. por exemplo. depois de consertar o json quebrado no seu exemplo, ele produz a seguinte saída:

$ jsonpipe < /tmp/nick.json 
/   {}
/content    []
/content/0  {}
/content/0/JOB_STATUS_ID    283739
/content/0/PROGRAM_ID   57
/content/0/STATUS   "Completed"
/content/0/**DATA_DATE**    "2017-03-09 00:00:00"
/content/0/**START_TIME**   "2017-03-10 00:46:13"
/content/0/END_TIME "2017-03-10 00:56:40"
/content/0/TOTAL_ROWS   null
/content/0/UPDATED_ROWS null
/content/0/DELETED_ROWS null
/content/0/INSERTED_ROWS    null
/content/0/REF1 "NULL"
/content/0/REF2 "NULL"
/content/0/AUD_CREATE_DT    "2017-03-10 00:46:13"
/content/0/AUD_CREATE_USER  "JOB_CONTROL"
/content/0/AUD_MODIFY_DT    "2017-03-10 00:56:40"
/content/0/AUD_MODIFY_USER  "JOB_CONTROL"
/content/1  {}
/content/1/JOB_STATUS_ID    109711
/content/1/PROGRAM_ID   57
/content/1/STATUS   "Completed"
/content/1/DATA_DATE    "2017-01-11 00:00:00"
/content/1/START_TIME   "2017-01-12 16:55:14"
/content/1/END_TIME "2017-01-12 18:54:51"
/content/1/TOTAL_ROWS   null
/content/1/UPDATED_ROWS null
/content/1/DELETED_ROWS null
/content/1/INSERTED_ROWS    null
/content/1/REF1 "NULL"
/content/1/REF2 "NULL"
/content/1/AUD_CREATE_DT    "2017-01-12 16:55:14"
/content/1/AUD_CREATE_USER  "JOB_CONTROL"
/content/1/AUD_MODIFY_DT    "2017-01-12"

Isso permite processá-lo com os utilitários de processamento de texto padrão. Por exemplo:

$ jsonpipe < /tmp/nick.json  | \
  sed -ne 's:^/content/0/\*\*DATA_DATE\*\*[[:space:]]\+::p'
"2017-03-09 00:00:00"

$ jsonpipe < /tmp/nick.json  | \
  awk -F'"' '/^\/content\/0\// && /DATA_DATE/ {print $2}'
2017-03-09 00:00:00

ou até mesmo algo tão grosseiro como este:

$ jsonpipe < /tmp/nick.json  | grep '/0/.*DATA_DATE'
/content/0/**DATA_DATE**    "2017-03-09 00:00:00"

Em sistemas debian e derivativos, ele é empacotado como python-jsonpipe e provavelmente tem um nome de pacote similar em outras distribuições. Ou pode ser encontrado no link

OBSERVAÇÃO: ele vem com uma ferramenta jsonunpipe correspondente, que você pode usar para converter esse formato voltado para linha em json - por exemplo, depois de modificá-lo com sed ou awk ou qualquer outra coisa.

    
por 19.07.2017 / 03:01