Я искал и видел много вопросов, похожих на мой, но ни одного ответа удовлетвори меня.
Мой сценарий: я пишу сценарий, который будет запускаться на сервере. У меня есть команда curl, которая возвращает тело json, и я хочу выбрать все значения с определенным ключом, и я могу не использовать какой-либо внешний инструмент для синтаксического анализа json, такого как jq, и у меня даже нет python, просто простая оболочка bash.
, поэтому мой вопрос: как мне это сделать, используя только оболочку по умолчанию?
для одного и того же ключа будет несколько значений, и я хочу создать массив этих значений.
пример json: -
{
"people":[
{
"id":"4568734",
"name":"suneel"
},
{
"id":"3678976",
"name":"adi"
}
]
}
если произносится «имя», то мне нужен массив («suneel» «adi»)
Примечание. Никаких внешних инструментов и только команды bash.
Функция удара как ниже может использоваться:
function jsonValue() {
KEY=$1
num=$2
awk -F"[,:}]" '{for(i=1;i<=NF;i++){if($i~/'$KEY'\042/){print $(i+1)}}}' | tr -d '"' | sed -n ${num}p
}
я сохранил эту функцию как jsonVal
и затем получил этот файл с помощью source jsonVal
. Можно очень хорошо использовать его в рамках сценария.
Это ожидает два аргумента. Первым аргументом является имя свойства. При необходимости во всех значениях пропустите второй аргумент. Если определенное значение необходимо, можно добавить второй аргумент как показано ниже.
[root@localhost Desktop]# cat data.json | jsonValue id
4568734
3678976
[root@localhost Desktop]# cat data.json | jsonValue id 1
4568734
[root@localhost Desktop]# cat data.json | jsonValue id 2
3678976
[root@localhost Desktop]# cat data.json | jsonValue name
suneel
adi
[root@localhost Desktop]# cat data.json | jsonValue name 1
suneel
[root@localhost Desktop]# cat data.json | jsonValue name 2
adi
[root@localhost Desktop]#
Hope это помогает.
Используя инструменты кроме надлежащих json синтаксических анализаторов всегда будет подвержено ошибкам или проблемам безопасности.
Ваш наилучший вариант: Если у Вас нет инструментов, необходимо сделать работу, попросить, чтобы администратор IT/Сервера установил их.
<час>Так или иначе, следующее будет работать, по крайней мере, на Ваш пример:
Используя grep -P
:
$ curl ... | grep -Po '"name":"\K[^"]*'
suneel
adi
С нормальным grep
:
$ curl ... | grep -o '"name":"[^"]*' | cut -d'"' -f4
suneel
adi
, Если Вы имеете "name"
где-нибудь за пределами "people"
, который Вы не хотите, это, очевидно, перестанет работать.
Это - немного излишества, но у меня уже есть приложение, которое читает метаданные Gmail для Повреждения ежедневных файлов резервных копий, сжатых и приложенных до сообщений Gmail. Формат файла подобен Вашему:
SAMPLE RECORD (REFORMATTED):
============================
{u'internalDate': u'1541947153000',
u'historyId': u'1517343',
u'payload':
{u'mimeType': u'multipart/mixed',
u'headers': [
{u'name': u'Return-Path', u'value': u'<me@gmail.com>'},
{u'name': u'Received', u'value': u'from alien (node-ISP. [IPv6.Address]) by smtp.gmail.com with ESMTPSA id x184-v6sm1211487pfx.42.2018.11.11.06.39.15 for <me@gmail.com> (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 11 Nov 2018 06:39:35 -0800 (PST)'},
{u'name': u'Message-ID', u'value': u'<5be83f27.1c69fb81.4f2bc.2906@mx.google.com>'},
{u'name': u'From', u'value': u'root <me@gmail.com>'},
{u'name': u'X-Google-Original-From', u'value': u'"root" <root@gmail.com>'},
{u'name': u'Received', u'value': u'by alien (sSMTP sendmail emulation); Sun, 11 Nov 2018 07:39:13 -0700'},
{u'name': u'Date', u'value': u'Sun, 11 Nov 2018 07:39:13 -0700'},
{u'name': u'to', u'value': u'me@gmail.com'},
{u'name': u'Subject', u'value': u'Daily-alien-Ubuntu-16.04-Backup-2018-11-11-Sunday.tar.gz.64'}
]
},
u'snippet': u'',
u'sizeEstimate': 18340047,
u'threadId': u'1670336bc9ac099d',
u'labelIds': [u'IMPORTANT', u'SENT', u'Label_12'],
u'id': u'1670336bc9ac099d'
}
Вот фрагмент кода из большого сценария удара:
GrepLine () {
#https://askubuntu.com/questions/952467/extracting-a-specific-string-after-a-given-string-from-html-file-using-a-bash-sc
End1="'"
Srch2="{u'name': u'Date', u'value': u'"
Srch3="{u'name': u'Subject', u'value': u'" # sometimes lower-case "subject"
End3="'}"
Srch4="u'sizeEstimate': "
End4=","
Srch5="u'labelIds': \[u'"
End5="]"
Srch6="u'id': u'"
# grep allows fast search (compiled C) and supports case insensitivity
HeaderDate=$(grep -oiPm1 "$Srch2\K[^$End1]+" <<< "$plLine")
HeaderSubject=$(grep -oiPm1 "$Srch3\K[^$End3]+" <<< "$plLine")
[[ $HeaderSubject == "" ]] && HeaderSubject="GREP ERROR: Subject blank"
Size=$(grep -oiPm1 "$Srch4\K[^$End4]+" <<< "$plLine")
LabelIds=$(grep -oiPm1 "$Srch5\K[^$End5]+" <<< "$plLine")
LabelIds="${LabelIds//\', u\'/$LabelSep}"
TrimLen="${#LabelIds}"
let TrimLen--
LabelIds="${LabelIds:0:TrimLen}" # Remove trailing '
# Convert "Label_12" to "Backup", etc.
ReplaceLabels
MessageId=$(grep -oiPm1 "$Srch6\K[^$End1]+" <<< "$plLine")
# Some email messages have 50 extra spaces or more.
HeaderSubject="${HeaderSubject%% }"
# Convert HTML to ASCII, eg: Can't wear the same one
# Replace external command: Line=$(sed 's/&/\&/g; s/</\</g;
# s/>/\>/g; s/"/\"/g; s/'/\'"'"'/g; s/“/\"/g;
# s/”/\"/g;' <<< "$Line") -- With faster builtin commands.
HeaderSubject="${HeaderSubject// / }"
HeaderSubject="${HeaderSubject//&/&}"
HeaderSubject="${HeaderSubject//</<}"
HeaderSubject="${HeaderSubject//>/>}"
HeaderSubject="${HeaderSubject//"/'"'}"
HeaderSubject="${HeaderSubject//'/"'"}"
HeaderSubject="${HeaderSubject//“/'"'}" # TODO: ASCII/ISO for opening quote
HeaderSubject="${HeaderSubject//”/'"'}" # TODO: ASCII/ISO for closing quote
# Truncate subject to 80 characters or whatever variable is set to
HeaderSubject="${HeaderSubject:0:$SubjectTruncate}"
HeaderSubject="${HeaderSubject//|/?}" # Strip out Yad array separators
HeaderSubject="${HeaderSubject//\--/==}" # Yad doesn't like --
# HeaderSubject="${HeaderSubject//\'/\"}" # Yad doesn't like
[[ $HeaderSubject == "" ]] && HeaderSubject="PARSING ERROR: Subject blank"
# Convert date to YAD format
HeaderDate=$(date -d "$HeaderDate" +'%Y-%m-%d')
} # GrepLine