سنفترض أنك على دراية بصيغة JSON وأنواع بياناتها.
يعمل jq بتمرير بيانات JSON الواردة عبر تعبير واحد (مكتوب على هيئة خط أنابيب من المُرشِّحات) للحصول على البيانات المحوّلة المطلوبة.
لغة jq يُنفّذها برنامجُ jq.
ويوفّر هذا البرنامج عدة خيارات مفيدة على سطر الأوامر للتحكم في كيفية استهلاك المُدخل وكيفية عرض المُخرج.
في الأمثلة أدناه ستُصادف:
-n أو --null-input
عادةً يُعطى برنامج jq ملفًا ليقرأه، أو تُرسل بيانات إلى مُدخله.
ويتيح لك الخيار --null-input توليد بيانات JSON دون أي مُدخلات.
-c أو --compact-output
يطبع jq مُخرجه بتنسيق جميل افتراضيًا.
ومن المفيد جدًا للبشر رؤية البيانات عندما تكون منسّقة بشكل جيد.
لكن ذلك ليس ضروريًا للآلات: فخيار --compact-output يزيل المسافات البيضاء الخاصة بالتنسيق لتقليل حجم JSON الناتج.
-f filename أو --from-file filename
اقرأ برنامج jq من filename بدلًا من تقديمه على سطر الأوامر.
ويستخدم كل من sed وawk الخيار -f للغرض نفسه.
وسترى هذا مستخدمًا في سكربتات الاختبار الخاصة بالتمارين التطبيقية.
ستركز بقية هذا الدرس على لغة jq.
يُعرف المُرشِّح أيضًا باسم التعبير.
يأخذ المُرشِّح مُدخلًا وينتج مُخرجًا.
وكما هو الحال عند العمل في صدفة يونكس، يمكنك ربط المُرشِّحات بأنبوب | لتوصيل مُخرج أحد المُرشِّحات بمُدخل آخر.
.
هذا أبسط مُرشِّح. إنه يمرّر مُدخله إلى مُخرجه ببساطة.
$ echo '[1, 2, 3]' | jq '.'
[
1,
2,
3
]
ستكون هذه مقدمة سريعة للتعامل مع المصفوفات. وسنغطي هذا الموضوع بمزيد من التفصيل لاحقًا.
يُوصَل إلى عناصر المصفوفة باستخدام الأقواس المربعة، وترقيمها يبدأ من الصفر.
$ echo '[10, 20, 30]' | jq '.[1]'
20
يمكن لـ المُرشِّح أن يبني مصفوفة بوضع تعبير بين [ و]
بقائمة معروفة من العناصر:
jq -n '[1, 2, 3]'
لتجميع تدفق من العناصر: على سبيل المثال،
range دالة تُخرج تدفقًا من الأعداد
$ jq -n 'range(10; 70; 15)'
10
25
40
55
واستخدام [] يجمع نتائج التعبير في مصفوفة
$ jq -c -n '[range(10; 70; 15)]'
[10,25,40,55]
الفاصلة ليست مجرد صياغة تفصل عناصر المصفوفة. الفاصلة عامل يضم التدفقات.
على سبيل المثال، [1, 2, 3] هو مُرشِّح يستخدم باني المصفوفة [] لجمع نتيجة ضم التعبيرات الثلاثة 1 و2 و3.
هل لاحظت الفواصل المنقوطة في range(10; 70; 15) أعلاه؟
ولأن الفواصل لها غرض محدد في لغة jq، تستخدم الدوال التي تأخذ عدة وسائط الفواصل المنقوطة للفصل بين الوسائط.
مقدمة سريعة إلى الكائنات.
على غرار كثير من لغات البرمجة، استخدم النقاط للوصول إلى خصائص الكائن
$ echo '{"foo": {"bar": "qux"}}' | jq '.foo.bar'
"qux"
يمكن استخدام الأقواس المربعة مع الكائنات أيضًا، لكن حينها تلزم علامات الاقتباس للسلاسل النصية الحرفية. وهذه إحدى الطرق للتعامل مع المفاتيح التي تحتوي على مسافات.
$ echo '{"foo bar": "qux"}' | jq '.["foo bar"]'
"qux"
يمكنك بناء كائن باستخدام {} وأزواج key: value.
ولا تلزم علامات الاقتباس حول المفاتيح التي تكون سلاسل نصية «بسيطة».
jq -n '{question: (6 * 9), answer: 42}'
يُخرج
{
"question": 54,
"answer": 42
}
لمعالجة المفتاح باعتباره تعبيرًا، عليك وضعه بين قوسين هلاليين (المثال التالي يُخرج أيضًا النتيجة نفسها أعلاه).
echo '[{"key":"question", "value":54}, {"key":"answer", "value":42}]' \
| jq '{(.[0].key): .[0].value, (.[1].key): .[1].value}'
على سبيل المثال، لدينا file.json يحتوي على
{
"key1": "value1",
"key2": [5, 15, 25]
}
لنحسب طول المصفوفة key2:
$ jq '.key2 | length' file.json
3
نحن نمرّر مُخرج تعبير .key2 عبر الأنبوب كمُدخل إلى length، الذي يُخرج كما هو متوقع عدد العناصر في المصفوفة.
في هذا المثال، تُتجاهَل بيانات JSON المُدخلة ولا تؤثر على المُخرج:
$ echo '{"answer": 42}' | jq '6 * 9'
54
يمكن لـ المُرشِّح أن يُخرج أكثر من قيمة.
على سبيل المثال، يُخرج المُرشِّح .[] كل عنصر من المصفوفة كقيمة منفصلة:
$ jq -n -c '[1, 2, 3]'
[1,2,3]
$ jq -n -c '[1, 2, 3] | .[]'
1
2
3
وتمرير هذا المُرشِّح عبر الأنبوب إلى آخر سيُنفّذ المُرشِّح الثاني لكل قيمة:
$ jq -n -c '[1, 2, 3] | .[] | . * 2'
2
4
6
هذا يشبه التكرار الضمني.
وبمجرد أن تفهم هذه التقنية، ستدرك أن مُرشِّحات jq القوية جدًا يمكن أن تكون موجزة جدًا.
تُستخدم الأقواس الهلالية لتجميع التعابير الفرعية معًا لفرض ترتيب العمليات، تمامًا كما في اللغات الأخرى.
وفي jq، قد تبدو الحاجة إليها مفاجئة إلى حد ما.
على سبيل المثال، لنفترض أننا نريد بناء مصفوفة بعنصرين: الجذر التربيعي للعدد 9؛ و_e_ مرفوعة إلى القوة 1.
والتعبيران المنفردان هما 9 | sqrt و1 | exp.
ونتوقع أن يكون المُخرج هو المصفوفة [3, 2.7...]
$ jq -n '[ 9|sqrt, 1|exp ]'
[
20.085536923187668,
2.718281828459045
]
لماذا لم نحصل على ما توقعناه؟ يفسّر jq ذلك على النحو التالي:
[ ((9|sqrt), 1) | exp ]
يبني jq تدفقًا من عنصرين (3 و1) يُعطى كل منهما إلى exp.
علينا أن نضمن أن exp يأخذ عددًا واحدًا فقط كمُدخل.
بعبارة أخرى، علينا أن نفرض تقييم الأنبوب قبل الفاصلة.
$ jq -n '[ 9|sqrt, (1|exp) ]'
[
3,
2.718281828459045
]
دون الخوض في عمق كبير (ستكون الدوال موضوعًا لتمرين آخر)، إليك بعض الدوال المدمجة المفيدة:
length
بمُدخل مصفوفة، أخرِج عدد العناصر في المصفوفة.
$ jq -n '[10, 20, 30, 40] | length'
4
+
يفعل هذا العامل أشياء مختلفة حسب نوع القيم التي يعمل عليها: فهو يجمع الأعداد، ويصل السلاسل النصية، ويُضيف المصفوفات، ويدمج الكائنات.
$ jq -c -n '
3 + 4,
"foo" + "bar",
["a", "b"] + ["c"],
{"m": 10} + {"n": 20}
'
7
"foobar"
["a","b","c"]
{"m":10,"n":20}
add دالة تأخذ مصفوفة وتُرجع عنصرًا جُمعت فيه كل العناصر معًا وفق قواعد +.
و[1, 2, 3] | add يُخرج 6.
map
بمُدخل مصفوفة ومُرشِّح كوسيط، أخرِج مصفوفة يُطبَّق فيها المُرشِّح على كل عنصر
$ jq -c -n '[10, 20, 30, 40] | map(. / 5)'
[2,4,6,8]
select
بمُدخل ما ومُرشِّح كوسيط:
null، بل لا مُخرج فعلًا)على سبيل المثال، بمُدخل بعض الأعداد، اختر تلك القابلة للقسمة على 3
$ jq -n 'range(10) | select(. % 3 == 0)'
0
3
6
9
تذكّر أن range يُخرج تدفقًا من الأعداد.
وسيُستدعى select مرة لكل عدد.
ولا تُخرَج إلا الأعداد «المارة» في التعبير.
غالبًا ما تحتاج إلى اختيار عناصر من مصفوفة. وهناك عدة أساليب للقيام بذلك.
بمُدخل ["Anne", "Bob", "Cathy", "Dave"]، اختر الأسماء التي طولها 4.
استخدم map وselect معًا
map(select(length == 4))
فكّك المصفوفة إلى عناصر، ثم طبّق select على ذلك التدفق، واجمع النتائج
[ .[] | select(length == 4) ]
تبدأ التعليقات بالمحرف # وتستمر إلى نهاية السطر.
لديك رغبة مفاجئة في أكل البان كيك. وبصفتك شخصًا عصريًا ذا ميول تقنية، تكتب قائمة تسوق لمكوّنات البان كيك بصيغة JSON. بنية القائمة هي:
{
"name": "name of shopping list",
"ingredients": [ ...list of ingredients... ],
"optional ingredients": [ ...list of ingredients... ]
}
يُمثَّل المكوّن ككائن JSON، هكذا:
{
"item": "flour",
"amount": {
"quantity": 2,
"unit": "cup"
}
}
للمكوّن خاصية اختيارية باسم "substitute" تحمل سلسلة نصية تمثل عنصرًا آخر يمكن استخدامه بدلًا منه.
لنرَ كيف يمكننا فحص قائمة التسوق باستخدام jq
اكتب تعبيرًا يُخرج عنصر "name" من قائمة التسوق.
احسب المكوّنات "required" فقط. لا تُدرج المكوّنات الاختيارية.
اكتب تعبيرًا يُخرج كمية السكر. المطلوب هو الجزء الرقمي فقط.
يمكن استبدال بعض المكوّنات (إذا لم يتوفر لديك المكوّن X يمكنك استخدام Y). أخرِج كائن JSON يربط كل مكوّن موصى به ببديله. أدرِج المكوّنات الاختيارية في الخريطة.
سجّل في Exercism لتتعلّم وتتقن jq عبر 12 مفهومًا75 تمرينًا، وإرشاد بشري حقيقي، وكل ذلك مجانًا.