أداة شبيهة بـ grep
تفهم بناء جملة التعليمات البرمجية المصدر وتسمح بالمعالجة بالإضافة إلى البحث.
مثل grep
، تعد التعبيرات العادية بدائية أساسية. على عكس grep
، تتيح الإمكانيات الإضافية دقة أعلى ، مع خيارات للتلاعب . يسمح هذا srgn
بالعمل على طول أبعاد التعبيرات العادية وأدوات IDE ( إعادة تسمية الكل ، البحث عن جميع المراجع ، ...) وحدها لا تستطيع استكمالها.
يتم تنظيم srgn
حول الإجراءات التي يجب اتخاذها (إن وجدت)، والتي تعمل فقط ضمن نطاقات دقيقة ومدركة لقواعد اللغة بشكل اختياري. فيما يتعلق بالأدوات الموجودة، فكر في الأمر كمزيج من tr
و sed
و ripgrep و tree-sitter
، بهدف تصميم بسيط : إذا كنت تعرف التعبير العادي وأساسيات اللغة التي تعمل بها، فمن الجيد أن تبدأ .
نصيحة
يتم التحقق من كافة مقتطفات التعليمات البرمجية المعروضة هنا كجزء من اختبارات الوحدة باستخدام ثنائي srgn
الفعلي. ما يتم عرضه هنا مضمون للعمل.
أبسط استخدام srgn
يعمل بشكل مشابه لـ tr
:
$ echo ' Hello World! ' | srgn ' [wW]orld ' ' there ' # replacement
Hello there !
يتم استبدال مطابقات نمط التعبير العادي '[wW]orld'
( النطاق ) ( الإجراء ) بالوسيطة الموضعية الثانية. يمكن تحديد صفر أو أكثر من الإجراءات:
$ echo ' Hello World! ' | srgn ' [wW]orld ' # zero actions: input returned unchanged
Hello World !
$ echo ' Hello World! ' | srgn --upper ' [wW]orld ' ' you ' # two actions: replacement, afterwards uppercasing
Hello YOU !
يتم دائمًا إجراء الاستبدال أولاً وتحديد موضعه. يتم تطبيق أي إجراءات أخرى بعد تقديمها كعلامات سطر الأوامر.
وبالمثل، يمكن تحديد أكثر من نطاق: بالإضافة إلى نمط regex، يمكن توفير نطاق مدرك لقواعد اللغة ، والذي يمتد إلى العناصر النحوية للكود المصدر (فكر، على سبيل المثال، "جميع تعريفات class
في Python" ). إذا تم توفير كليهما، فسيتم تطبيق نمط التعبير العادي فقط ضمن نطاق اللغة الأول . يتيح ذلك البحث والمعالجة بدقة لا تكون ممكنة عادةً باستخدام تعبيرات عادية عادية، ويخدم بُعدًا مختلفًا عن الأدوات مثل إعادة تسمية الكل في بيئة تطوير متكاملة (IDEs).
على سبيل المثال، خذ بعين الاعتبار ملف بايثون المصدر (غير المجدي):
"""Module for watching birds and their age."""
from dataclasses import dataclass
@ dataclass
class Bird :
"""A bird!"""
name : str
age : int
def celebrate_birthday ( self ):
print ( "?" )
self . age += 1
@ classmethod
def from_egg ( egg ):
"""Create a bird from an egg."""
pass # No bird here yet!
def register_bird ( bird : Bird , db : Db ) -> None :
assert bird . age >= 0
with db . tx () as tx :
tx . insert ( bird )
والتي يمكن البحث فيها باستخدام:
$ cat birds.py | srgn --python ' class ' ' age '
11: age: int
15: self.age += 1
تم البحث عن age
السلسلة والعثور عليه فقط ضمن تعريفات class
بايثون (وليس، على سبيل المثال، في الهيئات الوظيفية مثل register_bird
، حيث يحدث age
أيضًا وسيكون من المستحيل استبعاده من الاعتبار في Vanilla grep
). افتراضيًا، يقوم "وضع البحث" هذا أيضًا بطباعة أرقام الأسطر. يتم الدخول إلى وضع البحث إذا لم يتم تحديد أي إجراءات ، ويتم إعطاء لغة مثل --python
1 - فكر في الأمر مثل "ripgrep ولكن مع عناصر اللغة النحوية".
يمكن أيضًا إجراء البحث عبر الأسطر، على سبيل المثال للعثور على الأساليب (المعروفة أيضًا باسم def
ضمن class
) التي تفتقر إلى سلاسل المستندات:
$ cat birds.py | srgn --python ' class ' ' def .+:ns+[^"s]{3} ' # do not try this pattern at home
13: def celebrate_birthday(self):
14: print("?")
لاحظ كيف أن هذا لا يظهر إما from_egg
(يحتوي على سلسلة مستندية) أو register_bird
(ليس تابعًا، def
خارج class
).
يمكن تحديد نطاقات اللغة نفسها عدة مرات أيضًا. على سبيل المثال، في مقتطف الصدأ
pub enum Genre {
Rock ( Subgenre ) ,
Jazz ,
}
const MOST_POPULAR_SUBGENRE : Subgenre = Subgenre :: Something ;
pub struct Musician {
name : String ,
genres : Vec < Subgenre > ,
}
يمكن حفر عناصر متعددة جراحيًا إلى الأسفل
$ cat music.rs | srgn --rust ' pub-enum ' --rust ' type-identifier ' ' Subgenre ' # AND'ed together
2: Rock(Subgenre),
حيث يتم إرجاع الأسطر المطابقة لجميع المعايير فقط، والتي تعمل وكأنها منطقية وبين جميع الشروط. لاحظ أنه يتم تقييم الشروط من اليسار إلى اليمين، مما يمنع بعض المجموعات من أن تكون منطقية: على سبيل المثال، البحث عن نص class
Python داخل doc-strings
Python عادةً لا يُرجع شيئًا. معكوس يعمل كما هو متوقع ولكن:
$ cat birds.py | srgn --py ' class ' --py ' doc-strings '
8: """A bird!"""
19: """Create a bird from an egg."""
لا تظهر أي مستندات خارج الهيئات class
!
تغير العلامة -j
هذا السلوك: من التقاطع من اليسار إلى اليمين، إلى تشغيل جميع الاستعلامات بشكل مستقل وضم نتائجها، مما يسمح لك بالبحث بطرق متعددة في وقت واحد:
$ cat birds.py | srgn -j --python ' comments ' --python ' doc-strings ' ' bird[^s] '
8: """A bird!"""
19: """Create a bird from an egg."""
20: pass # No bird here yet!
تم العثور على نمط bird[^s]
داخل التعليقات أو سلاسل المستندات بالمثل، وليس فقط "سلاسل المستندات داخل التعليقات".
إذا لم يتم توفير الإدخال القياسي، يعرف srgn
كيفية العثور على الملفات المصدر ذات الصلة تلقائيًا، على سبيل المثال في هذا المستودع:
$ srgn --python ' class ' ' age '
docs/samples/birds
11: age: int
15: self.age += 1
docs/samples/birds.py
9: age: int
13: self.age += 1
فهو يتنقل بشكل متكرر في دليله الحالي، ويبحث عن الملفات بناءً على امتدادات الملفات وخطوط shebang، ويعالجها بسرعة عالية جدًا. على سبيل المثال، تقوم srgn --go strings 'd+'
بالبحث عن وطباعة كل ما يقرب من 140.000 سلسلة من الأرقام في سلاسل Go الحرفية داخل قاعدة تعليمات Kubernetes التي تتكون من حوالي 3.000.000 سطر من كود Go خلال 3 ثوانٍ على 12 مركزًا لـ M3. لمزيد من المعلومات حول العمل مع العديد من الملفات، انظر أدناه.
يمكن الجمع بين النطاقات والإجراءات بشكل اعتباطي تقريبًا (على الرغم من أن العديد من المجموعات لن تكون مفيدة أو حتى ذات معنى). على سبيل المثال، خذ بعين الاعتبار مقتطف Python هذا (للحصول على أمثلة لاستخدام اللغات المدعومة الأخرى، انظر أدناه):
"""GNU module."""
def GNU_says_moo ():
"""The GNU function -> say moo -> ✅"""
GNU = """
GNU
""" # the GNU...
print ( GNU + " says moo" ) # ...says moo
الذي يتم تشغيل الأمر التالي عليه:
cat gnu.py | srgn --titlecase --python ' doc-strings ' ' (?' ' $1: GNU ? is not Unix '
تشريح هذا الاستدعاء هو:
--titlecase
(إجراء) سيعمل على كل ما تم العثور عليه في النطاق
--python 'doc-strings'
(نطاق) سوف يمتد إلى (على سبيل المثال، يأخذ في الاعتبار فقط) سلاسل المستندات وفقًا لقواعد لغة بايثون
'(? (نطاق) يرى فقط ما تم تحديد نطاقه بالفعل بواسطة الخيار السابق، وسيعمل على تضييق نطاقه أكثر. لا يمكن أبدا توسيع النطاق السابق. يتم تطبيق نطاق التعبير العادي بعد أي نطاق (نطاقات) لغة.
(? عبارة عن بناء جملة سلبي، مما يوضح كيفية توفر هذه الميزة المتقدمة. لن يتم أخذ سلاسل
GNU
المسبوقة بـ The
بعين الاعتبار.
'$1: GNU ? is not Unix'
(إجراء) سيستبدل كل تكرار مطابق (على سبيل المثال، كل قسم إدخال وجد أنه في النطاق) بهذه السلسلة. الأحداث المتطابقة هي أنماط '(? فقط ضمن مستندات Python. والجدير بالذكر أن سلسلة الاستبدال هذه توضح ما يلي:
$1
، والذي يحمل المحتويات التي تم التقاطها بواسطة مجموعة الالتقاط الأولى. هذا ([az]+)
لأن (? لا يلتقط.
يستخدم الأمر نطاقات متعددة (اللغة ونمط التعبير العادي) وإجراءات متعددة (الاستبدال وعنوان العنوان). ثم تقرأ النتيجة
"""Module: GNU ? Is Not Unix."""
def GNU_says_moo ():
"""The GNU function -> say moo -> ✅"""
GNU = """
GNU
""" # the GNU...
print ( GNU + " says moo" ) # ...says moo
حيث تقتصر التغييرات على:
- """GNU module."""
+ """Module: GNU ? Is Not Unix."""
def GNU_says_moo():
"""The GNU -> say moo -> ✅"""
تحذير
أثناء وجود srgn
في مرحلة تجريبية (الإصدار الرئيسي 0)، تأكد من معالجة الملفات التي يمكنك استعادتها بأمان فقط (بشكل متكرر).
لا يقوم وضع البحث بالكتابة فوق الملفات، لذا فهو آمن دائمًا.
انظر أدناه للحصول على مخرجات المساعدة الكاملة للأداة.
ملحوظة
اللغات المدعومة هي
قم بتنزيل ثنائي تم إنشاؤه مسبقًا من الإصدارات.
يوفر هذا الصندوق ثنائياته بتنسيق متوافق مع cargo-binstall
:
cargo install cargo-binstall
(قد يستغرق بعض الوقت)cargo binstall srgn
(بضع ثوانٍ، حيث يقوم بتنزيل الثنائيات المعدة مسبقًا من GitHub)هذه الخطوات مضمونة النجاح، حيث تم اختبارها في CI. كما أنها تعمل أيضًا في حالة عدم توفر ثنائيات تم إنشاؤها مسبقًا لنظامك الأساسي، حيث ستعود الأداة إلى التجميع من المصدر.
الصيغة متاحة عبر:
brew install srgn
متاح عبر غير مستقر:
nix-shell -p srgn
متاح عبر AUR.
يتوفر منفذ:
sudo port install srgn
تأتي جميع صور مشغل GitHub Actions مع cargo
مثبتة مسبقًا، ويوفر cargo-binstall
إجراء GitHub مناسبًا:
jobs :
srgn :
name : Install srgn in CI
# All three major OSes work
runs-on : ubuntu-latest
steps :
- uses : cargo-bins/cargo-binstall@main
- name : Install binary
run : >
cargo binstall
--no-confirm
srgn
- name : Use binary
run : srgn --version
ينتهي ما ورد أعلاه في إجمالي 5 ثوانٍ فقط، حيث لا يلزم إجراء تجميع. لمزيد من السياق، راجع نصيحة cargo-binstall
بشأن CI.
على نظام Linux، يعمل gcc
.
على نظام التشغيل macOS، استخدم clang
.
على نظام التشغيل Windows، يعمل MSVC.
حدد "تطوير سطح المكتب باستخدام C++" عند التثبيت.
cargo install srgn
cargo add srgn
انظر هنا للمزيد.
يتم دعم الأصداف المختلفة للنصوص البرمجية لإكمال الصدفة. على سبيل المثال، قم بإلحاق eval "$(srgn --completions zsh)"
بـ ~/.zshrc
للإكمالات في ZSH. يمكن أن تبدو الجلسة التفاعلية بعد ذلك كما يلي:
تم تصميم الأداة حول النطاقات والإجراءات . تعمل النطاقات على تضييق نطاق أجزاء الإدخال المراد معالجتها. الإجراءات ثم تنفيذ المعالجة. بشكل عام، كل من النطاقات والإجراءات قابلة للتركيب، لذلك يمكن تمرير أكثر من واحد منها. كلاهما اختياريان (ولكن عدم اتخاذ أي إجراء لا معنى له)؛ تحديد عدم وجود نطاق يعني أن الإدخال بأكمله موجود في النطاق.
في الوقت نفسه، هناك تداخل كبير مع tr
البسيط: تم تصميم الأداة لتكون متوافقة بشكل وثيق مع حالات الاستخدام الأكثر شيوعًا، ولا تتجاوز ذلك إلا عند الحاجة.
أبسط عمل هو الاستبدال. يتم الوصول إليه خصيصًا (كوسيطة، وليس كخيار) للتوافق مع tr
وبيئة العمل العامة. يتم تقديم جميع الإجراءات الأخرى كعلامات، أو خيارات إذا أخذت قيمة.
على سبيل المثال، تعمل الاستبدالات البسيطة المكونة من حرف واحد كما في tr
:
$ echo ' Hello, World! ' | srgn ' H ' ' J '
Jello, World!
الوسيطة الأولى هي النطاق (الحرف H
في هذه الحالة). أي شيء يطابقه يخضع للمعالجة (الاستبدال بـ J
، الوسيطة الثانية، في هذه الحالة). ومع ذلك، لا يوجد مفهوم مباشر لفئات الأحرف كما في tr
. بدلاً من ذلك، بشكل افتراضي، النطاق هو نمط تعبير عادي، لذلك يمكن استخدام فئاته لتأثير مماثل:
$ echo ' Hello, World! ' | srgn ' [a-z] ' ' _ '
H____, W____!
يحدث الاستبدال بجشع عبر المباراة بأكملها افتراضيًا (لاحظ فئة أحرف UTS، التي تذكرنا بـ tr
's [:alnum:]
):
$ echo ' ghp_oHn0As3cr3T!! ' | srgn ' ghp_[[:alnum:]]+ ' ' * ' # A GitHub token
*!!
يتم دعم ميزات regex المتقدمة، على سبيل المثال عمليات البحث:
$ echo ' ghp_oHn0As3cr3T ' | srgn ' (?<=ghp_)[[:alnum:]]+ ' ' * '
ghp_*
احرص على استخدامها بأمان، حيث أن الأنماط المتقدمة تأتي دون ضمانات معينة للسلامة والأداء. إذا لم يتم استخدامها، فلن يتأثر الأداء.
لا يقتصر الاستبدال على حرف واحد. يمكن أن يكون أي سلسلة، على سبيل المثال لإصلاح هذا الاقتباس:
$ echo ' "Using regex, I now have no issues." ' | srgn ' no issues ' ' 2 problems '
"Using regex, I now have 2 problems."
الأداة متوافقة تمامًا مع Unicode، مع دعم مفيد لبعض فئات الأحرف المتقدمة:
$ echo ' Mood: ? ' | srgn ' ? ' ' ? '
Mood: ?
$ echo ' Mood: ???? :( ' | srgn ' p{Emoji_Presentation} ' ' ? '
Mood: ???? :(
البدائل على علم بالمتغيرات، والتي يمكن الوصول إليها للاستخدام من خلال مجموعات التقاط regex. يمكن ترقيم مجموعات الالتقاط أو تسميتها اختياريًا. تتوافق مجموعة الالتقاط الصفرية مع المباراة بأكملها.
$ echo ' Swap It ' | srgn ' (w+) (w+) ' ' $2 $1 ' # Regular, numbered
It Swap
$ echo ' Swap It ' | srgn ' (w+) (w+) ' ' $2 $1$1$1 ' # Use as many times as you'd like
It SwapSwapSwap
$ echo ' Call +1-206-555-0100! ' | srgn ' Call (+?d-d{3}-d{3}-d{4}).+ ' ' The phone number in "$0" is: $1. ' # Variable `0` is the entire match
The phone number in "Call +1-206-555-0100!" is: +1-206-555-0100.
حالة الاستخدام الأكثر تقدمًا هي، على سبيل المثال، إعادة بناء التعليمات البرمجية باستخدام مجموعات الالتقاط المسماة (ربما يمكنك التوصل إلى حالة أكثر فائدة...):
$ echo ' let x = 3; ' | srgn ' let (?[a-z]+) = (?.+); ' ' const $var$var = $expr + $expr; '
const xx = 3 + 3;
كما هو الحال في bash، استخدم الأقواس المتعرجة لتوضيح المتغيرات من المحتوى المجاور مباشرة:
$ echo ' 12 ' | srgn ' (d)(d) ' ' $2${1}1 '
211
$ echo ' 12 ' | srgn ' (d)(d) ' ' $2$11 ' # will fail (`11` is unknown)
$ echo ' 12 ' | srgn ' (d)(d) ' ' $2${11 ' # will fail (brace was not closed)
نظرًا لأن الاستبدال هو مجرد سلسلة ثابتة، فإن فائدته محدودة. هذا هو المكان الذي تلعب فيه صلصة tr
السرية دورًا عادةً: استخدام فئات الشخصيات الخاصة بها، والتي تكون صالحة في المركز الثاني أيضًا، والترجمة بدقة من أعضاء الأول إلى الثاني. هنا، هذه الفئات هي بدلاً من ذلك تعبيرات عادية، وهي صالحة فقط في المركز الأول (النطاق). نظرًا لكون التعبير العادي عبارة عن آلة حالة، فمن المستحيل مطابقته لـ "قائمة الأحرف"، والتي في tr
هي الوسيطة الثانية (الاختيارية). لقد أصبح هذا المفهوم خارج النافذة وفقدت مرونته.
وبدلاً من ذلك، يتم استخدام الإجراءات المعروضة، والتي تم إصلاحها جميعًا. نظرة خاطفة على حالات الاستخدام الأكثر شيوعًا لـ tr
تكشف أن مجموعة الإجراءات المتوفرة تغطيها جميعًا تقريبًا! لا تتردد في تقديم مشكلة إذا لم تتم تغطية حالة الاستخدام الخاصة بك.
على الإجراء التالي.
يزيل كل ما تم العثور عليه من الإدخال. نفس اسم العلم كما في tr
.
$ echo ' Hello, World! ' | srgn -d ' (H|W|!) '
ello, orld
ملحوظة
نظرًا لأن النطاق الافتراضي يطابق الإدخال بالكامل، فمن الخطأ تحديد الحذف بدون نطاق.
يضغط تكرارات الأحرف المطابقة للنطاق في تكرارات فردية. نفس اسم العلم كما في tr
.
$ echo ' Helloooo Woooorld!!! ' | srgn -s ' (o|!) '
Hello World!
إذا تم تمرير فئة أحرف، فسيتم ضغط جميع أعضاء تلك الفئة في أي عضو فئة تمت مواجهته أولاً:
$ echo ' The number is: 3490834 ' | srgn -s ' d '
The number is: 3
الجشع في المطابقة لا يعدل، فاحذر:
$ echo ' Winter is coming... ??? ' | srgn -s ' ?+ '
Winter is coming... ???
ملحوظة
يتطابق النمط مع مسار الشمس بأكمله ، لذا لا يوجد شيء يمكن عصره. الصيف يسود.
عكس الجشع إذا كانت حالة الاستخدام تتطلب ذلك:
$ echo ' Winter is coming... ??? ' | srgn -s ' ?+? ' ' ☃️ '
Winter is coming... ☃️
ملحوظة
مرة أخرى، كما هو الحال مع الحذف، فإن تحديد الضغط بدون نطاق واضح يعد خطأً. وبخلاف ذلك، سيتم ضغط الإدخال بالكامل.
يقع جزء كبير من استخدام tr
ضمن هذه الفئة. انها واضحة جدا.
$ echo ' Hello, World! ' | srgn --lower
hello, world!
$ echo ' Hello, World! ' | srgn --upper
HELLO, WORLD!
$ echo ' hello, world! ' | srgn --titlecase
Hello, World!
يقوم بتفكيك المدخلات وفقًا لنموذج التسوية D، ثم يتجاهل نقاط التعليمات البرمجية الخاصة بفئة Mark (راجع الأمثلة). وهذا يعني تقريبًا: اتخاذ شخصية خيالية، ونزع القطع المتدلية، ورميها بعيدًا.
$ echo ' Naïve jalapeño ärgert mgła ' | srgn -d ' P{ASCII} ' # Naive approach
Nave jalapeo rgert mga
$ echo ' Naïve jalapeño ärgert mgła ' | srgn --normalize # Normalize is smarter
Naive jalapeno argert mgła
لاحظ كيف أن mgła
خارج نطاق NFD، لأنه "ذري" وبالتالي غير قابل للتحلل (على الأقل هذا ما يهمس به ChatGPT في أذني).
يستبدل هذا الإجراء رموز ASCII متعددة الأحرف بنقطة رمز مفرد مناسبة ونظيراتها الأصلية من Unicode.
$ echo ' (A --> B) != C --- obviously ' | srgn --symbols
(A ⟶ B) ≠ C — obviously
بدلًا من ذلك، إذا كنت مهتمًا بالرياضيات فقط، فاستخدم تحديد النطاق:
$ echo ' A <= B --- More is--obviously--possible ' | srgn --symbols ' <= '
A ≤ B --- More is--obviously--possible
نظرًا لوجود تطابق 1:1 بين رمز ASCII واستبداله، يكون التأثير عكسيًا 2 :
$ echo ' A ⇒ B ' | srgn --symbols --invert
A => B
لا يوجد سوى مجموعة محدودة من الرموز المدعومة حتى الآن، ولكن يمكن إضافة المزيد.
يستبدل هذا الإجراء التهجئة البديلة للأحرف الألمانية الخاصة (ae، oe، ue، ss) بإصداراتها الأصلية (ä، ö، ü، ß) 3 .
$ echo ' Gruess Gott, Neueroeffnungen, Poeten und Abenteuergruetze! ' | srgn --german
Grüß Gott, Neueröffnungen, Poeten und Abenteuergrütze!
يعتمد هذا الإجراء على قائمة الكلمات (قم بالتجميع بدون الميزة german
إذا كان هذا يؤدي إلى تضخيم الملف الثنائي لديك كثيرًا). لاحظ الميزات التالية حول المثال أعلاه:
Poeten
كما هو، بدلاً من أن يتحول بسذاجة وخطأ إلى Pöten
Abenteuergrütze
في أي قائمة كلمات معقولة، ولكن تم التعامل معها بشكل صحيح مع ذلكAbenteuer
جزء من كلمة مركبة، فقد ظل كما هو أيضًا، بدلاً من تحويله بشكل غير صحيح إلى Abenteür
Neueroeffnungen
بشكل خفي عنصر ue
لا تمتلكه الكلمة المكونة له ( neu
, Eröffnungen
) ، ولكن لا تزال تتم معالجتها بشكل صحيح (على الرغم من الأغلفة غير المتطابقة أيضًا).عند الطلب، قد يتم فرض بدائل، كما قد يكون مفيدًا للأسماء:
$ echo ' Frau Loetter steht ueber der Mauer. ' | srgn --german-naive ' (?<=Frau )w+ '
Frau Lötter steht ueber der Mauer.
ومن خلال النظرة الإيجابية إلى الأمام، لم يتم تحديد نطاق أي شيء سوى التحية، وبالتالي تم تغييره. ظل Mauer
بشكل صحيح كما هو، ولكن لم تتم معالجة ueber
. تمريرة ثانية تصلح هذا:
$ echo ' Frau Loetter steht ueber der Mauer. ' | srgn --german-naive ' (?<=Frau )w+ ' | srgn --german
Frau Lötter steht über der Mauer.
ملحوظة
الخيارات والأعلام المتعلقة ببعض "الأصل" تكون مسبوقة باسم الوالدين، وسوف تشير ضمنًا إلى الأصل عند تقديمها، بحيث لا يلزم تمرير الأخير بشكل صريح. لهذا السبب تم تسمية --german-naive
كما هي، ولا يلزم تمرير --german
.
قد يتغير هذا السلوك بمجرد أن يدعم clap
تسلسل الأوامر الفرعية.
لا يمكن تحديد بعض الفروع لهذه الأداة المتواضعة، لأنها تعمل بدون سياق لغوي. على سبيل المثال، تعتبر كل من Busse
(الحافلات) و Buße
(الكفارة) كلمات قانونية. افتراضيًا، يتم تنفيذ عمليات الاستبدال بجشع إذا كانت قانونية (وهذا هو الهدف الأساسي من srgn
، بعد كل شيء)، ولكن هناك علامة لتبديل هذا السلوك:
$ echo ' Busse und Geluebte ' | srgn --german
Buße und Gelübte
$ echo ' Busse ? und Fussgaenger ?♀️ ' | srgn --german-prefer-original
Busse ? und Fußgänger ?♀️
معظم الإجراءات قابلة للتركيب، إلا إذا كان ذلك غير منطقي (مثل الحذف). ترتيب تطبيقها ثابت، وبالتالي فإن ترتيب العلامات المعطاة ليس له أي تأثير (الأنابيب المتعددة تعمل كبديل، إذا لزم الأمر). الاستبدالات تحدث دائمًا أولاً. بشكل عام، تم تصميم واجهة سطر الأوامر (CLI) لمنع سوء الاستخدام والمفاجآت: فهي تفضل التصادم على القيام بشيء غير متوقع (وهو أمر ذاتي بالطبع). لاحظ أن الكثير من المجموعات ممكنة من الناحية الفنية، ولكنها قد تؤدي إلى نتائج غير منطقية.
قد يبدو الجمع بين الإجراءات كما يلي:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu
KOEFFIZIENTEN ≠ BRÜCKEN...
يمكن تحديد نطاق أضيق، وينطبق على جميع الإجراءات بالتساوي:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu ' bw{1,8}b '
Koeffizienten != BRÜCKEN...
حدود الكلمات مطلوبة وإلا ستتم مطابقة Koeffizienten
مع Koeffizi
و enten
. لاحظ كيف لا يمكن، على سبيل المثال، الضغط على الفترات اللاحقة. النطاق المطلوب لـ .
سوف تتداخل مع واحد معين. الأنابيب العادية تحل هذا:
$ echo ' Koeffizienten != Bruecken... ' | srgn -Sgu ' bw{1,8}b ' | srgn -s ' . '
Koeffizienten != BRÜCKEN.
ملاحظة: يمكن التحايل على هروب التعبير العادي ( .
) باستخدام النطاق الحرفي. إجراء الاستبدال المعالج خصيصًا قابل للتركيب أيضًا:
$ echo ' Mooood: ????!!! ' | srgn -s ' p{Emoji} ' ' ? '
Mooood: ?!!!
يتم أولاً استبدال جميع الرموز التعبيرية، ثم الضغط عليها. لاحظ كيف لا يتم ضغط أي شيء آخر.
النطاقات هي مفهوم القيادة الثاني لـ srgn
. في الحالة الافتراضية، النطاق الرئيسي هو تعبير عادي. يعرض قسم الإجراءات حالة الاستخدام هذه بشيء من التفصيل، لذلك لن يتم تكرارها هنا. يتم تقديمه كحجة موضعية أولى.
يقوم srgn
بتوسيع هذا من خلال نطاقات معدة ومدركة لقواعد اللغة، والتي أصبحت ممكنة من خلال مكتبة tree-sitter
الممتازة. وهو يوفر ميزة الاستعلامات، والتي تعمل بشكل يشبه إلى حد كبير مطابقة الأنماط مع بنية بيانات الشجرة.
يأتي srgn
مرفقًا بمجموعة من أكثر هذه الاستعلامات فائدة. من خلال واجهة برمجة التطبيقات (API) القابلة للاكتشاف (إما كمكتبة أو عبر CLI، srgn --help
)، يمكن للمرء التعرف على اللغات المدعومة والاستعلامات المتاحة والمجهزة. تأتي كل لغة مدعومة مزودة بفتحة هروب، مما يسمح لك بتشغيل استعلاماتك المخصصة والمخصصة. تأتي الفتحة في شكل --lang-query
، حيث lang
هي لغة مثل python
. انظر أدناه لمعرفة المزيد حول هذا الموضوع المتقدم.
ملحوظة
يتم تطبيق نطاقات اللغة أولاً ، لذا مهما كان التعبير العادي المعروف أيضًا باسم النطاق الرئيسي الذي تمرره، فإنه يعمل على كل بنية لغة متطابقة بشكل فردي.
يعرض هذا القسم أمثلة لبعض الاستعلامات المعدة .
unsafe
(Rust) إحدى ميزات الكلمة الأساسية unsafe
في Rust هي "قابلية التأثر". ومع ذلك، فإن rg 'unsafe'
سيظهر بالطبع جميع مطابقات السلسلة (يساعد rg 'bunsafeb'
إلى حد ما)، وليس فقط تلك الموجودة في الكلمة الأساسية الفعلية للغة Rust. srgn
يساعد على جعل هذا أكثر دقة. على سبيل المثال:
// Oh no, an unsafe module!
mod scary_unsafe_operations {
pub unsafe fn unsafe_array_access ( arr : & [ i32 ] , index : usize ) -> i32 {
// UNSAFE: This function performs unsafe array access without bounds checking
* arr . get_unchecked ( index )
}
pub fn call_unsafe_function ( ) {
let unsafe_numbers = vec ! [ 1 , 2 , 3 , 4 , 5 ] ;
println ! ( "About to perform an unsafe operation!" ) ;
let result = unsafe {
// Calling an unsafe function
unsafe_array_access ( & unsafe_numbers , 10 )
} ;
println ! ( "Result of unsafe operation: {}" , result ) ;
}
}
يمكن البحث عنها