المسارات
/
jq
jq
/
المنهج
/
الأساسيات
ال

الأساسيات في jq

1 تمرين

نبذة عن الأساسيات

تعمل jq بتمرير بيانات JSON الواردة عبر تعبير واحد (مكتوب كـ_خط أنابيب من المرشِّحات_) للحصول على البيانات المحوَّلة المطلوبة.

مقدمة سريعة إلى خيارات سطر أوامر jq

لغة 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 للغرض نفسه. سترى هذا مستخدمًا في نصوص الاختبار الخاصة بالتمارين التدريبية.

راجع الدليل للحصول على تفاصيل حول جميع الخيارات.

المرشِّحات والأنابيب

المرشِّحات تُعرف أيضًا باسم التعبيرات.

المرشِّح يأخذ مدخلًا وينتج مخرجًا. وكما تعمل في صدفة Unix، يمكنك ربط المرشِّحات بأنبوب | لتوصيل مخرجات أحدها بمدخلات آخر.

مرشِّح الهوية: .

هذا أبسط مرشِّح. إنه يمرّر مدخلاته إلى مخرجاته ببساطة. على سبيل المثال، يطبع jq بتنسيق جميل افتراضيًا، لذا فإن تمرير JSON إلى مرشِّح . يمنحك مخرجات منسّقة بشكل جميل مجانًا!

$ 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 '[["question", "answer"], [54, 42]]' \
| jq '{(.[0][0]): .[1][0], (.[0][1]): .[1][1]}'
Note

من الشائع جدًا أن ترغب في استخراج مجموعة فرعية من المفاتيح من كائن كبير. على سبيل المثال، لاستخراج id وname من

{
    "id": 101,
    "name": "alpha widget",
    "specifications": {...}
}

يمكننا كتابة

{id: .id, name: .name}

لكن هذا شائع جدًا، لذا توجد صياغة مختصرة له:

{id, name}

خطوط الأنابيب

على سبيل المثال، إذا كان لدينا file.json يحتوي على

{
  "key1": "value1",
  "key2": [5, 15, 25]
}

لنحسب طول المصفوفة key2:

$ jq '.key2 | length' file.json
3

نحن نمرّر مخرجات تعبير .key2 عبر الأنبوب كمدخل إلى length، الذي يُخرج كما هو متوقّع عدد العناصر في المصفوفة.

Caution

هذا جانب من jq يحتاج إلى بعض التعوّد. معظم الدوال (وليس كلها) تتصرّف مثل المرشِّحات، حيث تمرّر البيانات إلى مدخل المرشِّح، لا كوسيط.

يمكن للمرشِّحات تجاهل مدخلاتها

في هذا المثال، تُتجاهَل بيانات 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
]

الأنواع

من الدليل

تدعم jq المجموعة نفسها من أنواع البيانات التي يدعمها JSON: الأعداد والسلاسل النصية والقيم المنطقية والمصفوفات والكائنات (وهي في لغة JSON تجزئات لا تحتوي إلا على مفاتيح نصية)، و"null".

ستتعلّم المزيد عنها في التمارين اللاحقة.

المسافات البيضاء

المسافات البيضاء ليست ذات دلالة في jq. استخدم المسافات/علامات الجدولة/الأسطر الجديدة كما تراه مناسبًا لتنسيق الكود. لا نعرف أي أدلة أساليب موجودة لـ jq.

قيم غير قابلة للتغيير

القيم في jq غير قابلة للتغيير. المرشِّحات التي تعدّل قيمةً ستُخرج قيمة جديدة. يعني هذا أن jq ليس لديه متغيرات عامة. ستحتاج إلى التعوّد على تمرير الحالة من مرشِّح إلى آخر.

"الصدقية"

تُعتبر القيمتان false وnull خطأ. وأي قيمة أخرى (بما في ذلك العدد صفر والسلسلة النصية/المصفوفة/الكائن الفارغة) تُعتبر صحيحًا.

الدوال والعوامل

دون الخوض في عمق كبير (ستكون الدوال موضوعًا لتمرين آخر)، إليك بعض الدوال المدمجة المفيدة:

  • 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) ]
      

التعليقات

تبدأ التعليقات بمحرف # وتستمر حتى نهاية السطر.

تعديل عبر GitHub يفتح الرابط في نافذة أو علامة تبويب جديدة

تعلّم الأساسيات