التعبيرات النمطية (regexes) هي تسلسلات من المحارف تحدّد نمط بحث في نصّ ما.
تعلّم صيغة التعبيرات النمطية خارج نطاق هذا الموضوع.
سنركّز على التعبيرات التي يوفّرها jq للاستفادة من التعبيرات النمطية.
تنفّذ الأدوات المختلفة إصدارات مختلفة من التعبيرات النمطية.
يضمّ jq مكتبة التعبيرات النمطية Oniguruma، وهي متوافقة إلى حد كبير مع تعبيرات Perl v5.8 النمطية.
يمكن العثور على الصيغة المحددة التي يستخدمها jq في مستودع Oniguruma على GitHub.
لا يمتلك jq أي صيغة خاصة للتعبيرات النمطية.
فهي تُعبَّر عنها ببساطة كسلاسل نصية.
وهذا يعني أن أي شرطات مائلة عكسية في التعبير النمطي يلزم تخطّيها داخل السلسلة النصية.
على سبيل المثال، يجب كتابة صنف المحارف الرقمية (\d) بالشكل "\\d".
تقتصر التعبيرات النمطية في jq على مجموعة من المُرشِّحات.
عندما تحتاج إلى معرفة ما إذا كانت سلسلة نصية تطابق نمطًا ما، فاستخدم مُرشِّح test.
STRING | test(REGEX)
STRING | test(REGEX; FLAGS)
STRING | test([REGEX, FLAGS])
يُخرج هذا المُرشِّح نتيجة منطقية.
"Hello World!" | test("W") # => true
"Goodbye Mars" | test("W") # => false
عندما تحتاج إلى استخراج السلسلة النصية الفرعية التي طابقت النمط فعلًا، فاستخدم مُرشِّح match.
STRING | match(REGEX)
STRING | match(REGEX; FLAGS)
STRING | match([REGEX, FLAGS])
يُخرج هذا المُرشِّح:
يبحث هذا المثال عن حرفَي علة متتاليين متماثلين باستخدام صيغة الإحالة الخلفية، \1.
"Hello World!" | match("([aeiou])\\1")
# => empty
"Goodbye Mars" | match("([aeiou])\\1")
# => {
# "offset": 1,
# "length": 2,
# "string": "oo",
# "captures": [
# {
# "offset": 1,
# "length": 1,
# "string": "o",
# "name": null
# }
# ]
# }
يُرجع مُرشِّح match كائنًا لكل مطابقة.
يوضّح هذا المثال مفعول العلم "g" في العثور على جميع حروف العلة.
"Goodbye Mars" | match("[aeiou]"; "g")
# => { "offset": 1, "length": 1, "string": "o", "captures": [] }
# { "offset": 2, "length": 1, "string": "o", "captures": [] }
# { "offset": 6, "length": 1, "string": "e", "captures": [] }
# { "offset": 9, "length": 1, "string": "a", "captures": [] }
على غرار مُرشِّح match، يُرجع مُرشِّح capture كائنًا إذا وُجدت مطابقة.
STRING | capture(REGEX)
STRING | capture(REGEX; FLAGS)
STRING | capture([REGEX, FLAGS])
الكائن المُرجَع يربط الالتقاطات المُسمّاة بأسمائها.
"JIRAISSUE-1234" | capture("(?<project>\\w+)-(?<issue_num>\\d+)")
# => {
# "project": "JIRAISSUE",
# "issue_num": "1234"
# }
مُرشِّح scan شبيه بـmatch مع العلم "g".
STRING | scan(REGEX)
STRING | scan(REGEX; FLAGS)
# note, there is no scan([REGEX, FLAGS]) version, unlike other filters
سيُخرج scan تدفقًا من السلاسل النصية الفرعية.
"Goodbye Mars" | scan("[aeiou]")
# => "o"
# "o"
# "e"
# "a"
استخدم مُنشئ المصفوفة [...] لالتقاط السلاسل النصية الفرعية.
"Goodbye Mars" | [ scan("[aeiou]") ]
# => ["o", "o", "e", "a"]
إذا كنت تعرف أجزاء السلسلة النصية التي تريد الاحتفاظ بها، فاستخدم match أو scan.
وإذا كنت تعرف الأجزاء التي تريد التخلّص منها، فاستخدم split.
STRING | split(REGEX; FLAGS)
يتعامل مُرشِّح split ذو الوسيط الواحد مع وسيطه كـسلسلة نصية ثابتة.
لاستخدام تعبير نمطي مع split، يجب توفير الوسيط الثاني؛ ولا بأس في استخدام سلسلة نصية فارغة.
مثال يقسّم سلسلة نصية عند أيّ مسافات بيضاء.
"first second third fourth" | split("\\s+"; "")
# => ["first", "second", "third", "fourth"]
هذا ما يحدث إذا نسينا وسيط الأعلام.
"first second third fourth" | split("\\s+")
# => ["first second third fourth"]
نتيجة واحدة فقط: لم تُرَ السلسلة النصية الثابتة \s+ في المدخل.
لا يستطيع split ذو الوسيط الواحد التعامل مع فراغات عشوائية.
والتقسيم عند مسافة يعطي هذه النتيجة.
"first second third fourth" | split(" ")
# => ["first", "", "", "second", "", "", "", "",
# "", "", "", "", "", "", "third", "fourth" ]
يستطيع مُرشِّحا sub وgsub تحويل السلسلة النصية المدخلة، باستبدال الأجزاء المطابقة من المدخل بسلسلة نصية بديلة.
لاستبدال أول مطابقة فقط، استخدم sub.
ولاstبدال جميع المطابقات، استخدم gsub.
STRING | sub(REGEX; REPLACEMENT)
STRING | sub(REGEX; REPLACEMENT; FLAGS)
STRING | gsub(REGEX; REPLACEMENT)
STRING | gsub(REGEX; REPLACEMENT; FLAGS)
"Goodnight kittens. Goodnight mittens." | sub("night"; " morning")
# => "Good morning kittens. Goodnight mittens."
"Goodnight kittens. Goodnight mittens." | gsub("night"; " morning")
# => "Good morning kittens. Good morning mittens."
يمكن لنص الاستبدال أن يشير إلى السلاسل النصية الفرعية المطابقة؛ استخدم الالتقاطات المُسمّاة وإقحام السلاسل النصية.
"Some 3-letter acronyms: gnu, csv, png"
| gsub( "\\b(?<tla>[[:alpha:]]{3})\\b"; # find words 3 letters long
"\(.tla | ascii_upcase)" ) # upper-case the match
# => "Some 3-letter acronyms: GNU, CSV, PNG"
في جميع المُرشِّحات أعلاه، FLAGS سلسلة نصية تتكوّن من صفر أو أكثر من الأعلام المدعومة.
g - البحث الشامل (العثور على جميع المطابقات، وليس الأولى فقط)i - بحث غير حسّاس لحالة الأحرفm - وضع الأسطر المتعددة (ستطابق '.' الأسطر الجديدة)n - تجاهل المطابقات الفارغةp - تفعيل الوضعين s و m معًاs - وضع السطر الواحد ('^' -> '\A', '$' -> '\Z')l - العثور على أطول المطابقات الممكنةx - صيغة التعبير النمطي الموسّعة (تجاهل المسافات البيضاء والتعليقات)على سبيل المثال
"JIRAISSUE-1234" | capture("(?<project>\\w+)-(?<issue_num>\\d+)")
# or with Extended formatting
"JIRAISSUE-1234" | capture("
(?<project> \\w+ ) # the Jira project
- # followed by a hyphen
(?<issue_num> \\d+ ) # followed by digits
"; "x")