عبارات باقاعده (regex) دنبالههایی از کاراکترها هستند که یک الگوی جستوجو در متن را مشخص میکنند.
یادگیری نحوهی نگارش عبارات باقاعده فراتر از حیطهی این مبحث است.
ما بر عبارتهایی تمرکز میکنیم که jq برای استفاده از عبارات باقاعده در اختیار میگذارد.
ابزارهای مختلف نسخههای متفاوتی از عبارات باقاعده را پیادهسازی میکنند.
jq کتابخانهی regex Oniguruma را در خود دارد که تا حد زیادی با عبارات باقاعدهی Perl v۵.۸ سازگار است.
نحوهی نگارش خاصی که jq استفاده میکند را میتوان در مخزن GitHub پروژهی Oniguruma پیدا کرد.
jq هیچ نحوهی نگارش خاصی برای عبارات باقاعده ندارد.
آنها بهسادگی بهصورت رشته بیان میشوند.
یعنی هر بکاسلشی که در عبارت باقاعده هست باید در رشته escape شود.
برای مثال، کلاس کاراکتر رقم (\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])
این فیلتر این موارد را بهعنوان خروجی میدهد:
این مثال با استفاده از نحوهی نگارش backref، یعنی \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": [] }
فیلتر capture مانند فیلتر match در صورت وجود تطبیق یک شیء برمیگرداند.
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 با ۱ آرگومان، آرگومان خود را بهعنوان یک رشتهی ثابت در نظر میگیرد.
برای استفاده از یک regex با 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 استفاده کنید.
برای جایگزینی همهی تطبیقها، از 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 - قالب توسعهیافتهی regex (فاصلههای سفید و توضیحات نادیده گرفته میشوند)برای مثال
"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")