Баш, получить значение из линии JSON

Система

Linux local 5.0.0-27-lowlatency #28-Ubuntu SMP PREEMPT Tue Aug 20 20:33:37 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

Выпуск

У меня есть входной файл.

{ "article": {"code": "01333457004","name": "ALAZANIS VALLEY 2015","note": "ČERV VÍNO EVROPA VÝCH OSTATNÍ","sel_unit": "Kus","unit_price": 229.0,"category": "ČERVENÉ,POLOSLADKÉ","unit": "L","EAN": "4867601700052","unit_volume": 0.75,"producer": null,"tax": 21.0,"text": "Alazanis Valley 2015;Gruzie,Kachetie;červené polsladké;750ml;16°C;Alazanis Valley 2015;Gruzie,Kachetie;červené polsladké;750ml;16°C;","is_action": "1","action_from": "20190905","action_to": "20190918","ordered_from": "20190126","ordered_to": "20190830","shelf_id": "1030542","is_outlet": 0}}

Как я могу получить только этот вывод (некоторые столбцы)?

"code": "01333457004","name": "ALAZANIS VALLEY 2015","is_action": "1","action_from": "20190905","action_to": "20190918"

Нет jq или других приложений, мне нужно просто bash sed или awk, или некоторые базовые команды, у меня нет прав администратора для его установки.

Я пробовал

Я пробовал cut, но есть проблема с разделителем , (иногда в ").

Спасибо.

1
задан 16 September 2019 в 14:14

3 ответа

Можно попробовать это:

grep -o '"[^"]*"\s*:\s*"[^"]*"' | \
grep -E '^"(code|name|is_action|action_from|action_to)"' | \
tr '\n' ',' | \
sed 's/,$//'

Детали :

  • grep -o '"[^"]*"\s*:\s*"[^"]*"' находят весь "key": "value" пары, и печатает их на отдельных строках;

Пример:

echo '{ "article": {"code": "01333457004","name": "ALAZANIS VALLEY 2015","note": "ČERV VÍNO EVROPA VÝCH OSTATNÍ","sel_unit": "Kus","unit_price": 229.0,"category": "ČERVENÉ,POLOSLADKÉ","unit": "L","EAN": "4867601700052","unit_volume": 0.75,"producer": null,"tax": 21.0,"text": "Alazanis Valley 2015;Gruzie,Kachetie;červené polsladké;750ml;16°C;Alazanis Valley 2015;Gruzie,Kachetie;červené polsladké;750ml;16°C;","is_action": "1","action_from": "20190905","action_to": "20190918","ordered_from": "20190126","ordered_to": "20190830","shelf_id": "1030542","is_outlet": 0}}' | grep -o '"[^"]*"\s*:\s*"[^"]*"'

Вывод:

"code": "01333457004"
"name": "ALAZANIS VALLEY 2015"
"note": "ČERV VÍNO EVROPA VÝCH OSTATNÍ"
"sel_unit": "Kus"
"category": "ČERVENÉ,POLOSLADKÉ"
"unit": "L"
"EAN": "4867601700052"
"text": "Alazanis Valley 2015;Gruzie,Kachetie;červené polsladké;750ml;16°C;Alazanis Valley 2015;Gruzie,Kachetie;červené polsladké;750ml;16°C;"
"is_action": "1"
"action_from": "20190905"
"action_to": "20190918"
"ordered_from": "20190126"
"ordered_to": "20190830"
"shelf_id": "1030542"
  • grep -E '^"(code|name|is_action|action_from|action_to)"' фильтрам только были нужны ключи.

Вывод:

"code": "01333457004"
"name": "ALAZANIS VALLEY 2015"
"is_action": "1"
"action_from": "20190905"
"action_to": "20190918"
  • tr '\n' ',' новая строка замены к запятой.

Вывод:

"code": "01333457004","name": "ALAZANIS VALLEY 2015","is_action": "1","action_from": "20190905","action_to": "20190918",
  • sed 's/,$//' удаляет в последний раз дополнительную запятую.

Вывод:

"code": "01333457004","name": "ALAZANIS VALLEY 2015","is_action": "1","action_from": "20190905","action_to": "20190918"

Полный пример

Команда:

echo '{ "article": {"code": "01333457004","name": "ALAZANIS VALLEY 2015","note": "ČERV VÍNO EVROPA VÝCH OSTATNÍ","sel_unit": "Kus","unit_price": 229.0,"category": "ČERVENÉ,POLOSLADKÉ","unit": "L","EAN": "4867601700052","unit_volume": 0.75,"producer": null,"tax": 21.0,"text": "Alazanis Valley 2015;Gruzie,Kachetie;červené polsladké;750ml;16°C;Alazanis Valley 2015;Gruzie,Kachetie;červené polsladké;750ml;16°C;","is_action": "1","action_from": "20190905","action_to": "20190918","ordered_from": "20190126","ordered_to": "20190830","shelf_id": "1030542","is_outlet": 0}}' | grep -o '"[^"]*"\s*:\s*"[^"]*"' | grep -E '^"(code|name|is_action|action_from|action_to)"' | tr '\n' ',' | sed 's/,$//'

Вывод:

"code": "01333457004","name": "ALAZANIS VALLEY 2015","is_action": "1","action_from": "20190905","action_to": "20190918"
2
ответ дан 10 November 2019 в 10:03
#!/bin/bash

declare -A JSON
a=$(
  grep -Po '\{.*\{\K(.*?)(?=\}\})' example.json |
  grep -Po '(^|,)\"\K(.*?)(?=\":)'
)
for b in $a; do
  JSON[$b]="$(grep -Po "\"$b\": \"?\K.*?(?=(\"?,\"|\}\}))" example.json)"
done


echo ${JSON[@]}
echo ${!JSON[@]}
echo ${JSON[name]}

или если Вы просто хотите значения:

grep -Po '\{.*\{\K(.*?)(?=\}\})' example.json | grep -Po "\".*?\": \"?\K.*?(?=(\"?,\"|$))"
0
ответ дан 10 November 2019 в 10:03

Хотя , сбои разделителя, можно использовать : разделитель с cut:

#!/bin/bash

# NAME: ParseJSON
# PATH: $HOME/askubuntu/
# DESC: Answer for: https://askubuntu.com/questions/1174505/bash-get-value-from-json-line
# DATE: September 16, 2019

Line='{ "article": {"code": "01333457004","name": "ALAZANIS VALLEY 2015","note": "ČERV VÍNO EVROPA VÝCH OSTATNÍ","sel_unit": "Kus","unit_price": 229.0,"category": "ČERVENÉ,POLOSLADKÉ","unit": "L","EAN": "4867601700052","unit_volume": 0.75,"producer": null,"tax": 21.0,"text": "Alazanis Valley 2015;Gruzie,Kachetie;červené polsladké;750ml;16°C;Alazanis Valley 2015;Gruzie,Kachetie;červené polsladké;750ml;16°C;","is_action": "1","action_from": "20190905","action_to": "20190918","ordered_from": "20190126","ordered_to": "20190830","shelf_id": "1030542","is_outlet": 0}}'

Code=$(echo "$Line" | cut -d':' -f3)
Code="${Code%,*}"                           # Remove ,"name"
Name=$(echo "$Line" | cut -d':' -f4)
Name="${Name%,*}"                           # Remove ,"note"
IsAction=$(echo "$Line" | cut -d':' -f15)
IsAction="${IsAction%,*}"                   # Remove ,"action_from"
ActionFrom=$(echo "$Line" | cut -d':' -f16)
ActionFrom="${ActionFrom%,*}"               # Remove ,"action_to"
ActionTo=$(echo "$Line" | cut -d':' -f17)
ActionTo="${ActionTo%,*}"                   # Remove ,"ordered_from"

echo '"code":'"$Code,"'"name":'"$Name,"'"is_action":'"$IsAction,"'"action_from":'"$ActionFrom,"'"action_to":'"$ActionTo"

я назвал сценарий ParseJSON, и это, он производится:

$ ParseJSON

"code": "01333457004","name": "ALAZANIS VALLEY 2015","is_action": "1","action_from":  "20190905","action_to": "20190918"
0
ответ дан 10 November 2019 в 10:03

Другие вопросы по тегам:

Похожие вопросы: