regex - شرح - there's a specific term for the patterns that grep lets you use




كيف نفعل مباراة غير الجشع في grep؟ (4)

أريد أن أقترب من أقصر مباراة وأن يكون النمط مثل:

<car ... model=BMW ...>
...
...
...
</car>

... يعني أي شخصية والإدخال هو خطوط متعددة.


grep

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

على سبيل المثال ، لجلب جميع الروابط إلى ملفات jpeg من محتوى الصفحة ، يمكنك استخدام:

grep -o '"[^" ]\+.jpg"'

للتعامل مع خطوط متعددة ، قم xargs الإدخال عبر xargs أولاً. للحصول على الأداء ، استخدم ripgrep .


الجواب المختصر هو استخدام التعبير العادي التالي:

(?s)<car .*? model=BMW .*?>.*?</car>
  • (؟ s) - هذا يجعل مباراة عبر متعدد
  • . *؟ - يطابق أي حرف ، عدة مرات بطريقة كسولة (الحد الأدنى من التطابق)

الإجابة (الأكثر) تعقيدًا هي:

(?s)<([a-z\-_0-9]+?) .*? model=BMW .*?>.*?</\1>

سيسمح هذا بمطابقة car1 و car2 في النص التالي

<car1 ... model=BMW ...>
...
...
...
</car1>
<car2 ... model=BMW ...>
...
...
...
</car2>
  • (..) يمثل مجموعة التقاط
  • يتطابق \ 1 في هذا السياق مع نص sametext كما تم مؤخرًا مع مجموعة الاستيلاء رقم 1

في الواقع .*? يعمل فقط في perl . أنا لست متأكدا من ما يعادل بنية regexp grep المكافئة. لحسن الحظ يمكنك استخدام بناء جملة بيرل مع grep بحيث grep -P ستعمل ولكن grep -E الذي هو نفس egrep لن ينجح (سيكون من الجشع).

انظر أيضا: http://blog.vinceliu.com/2008/02/non-greedy-regular-expression-matching.html


كنت تبحث عن مباراة غير الجشع (أو كسول). للحصول على تطابق غير الجشع في التعبيرات العادية تحتاج إلى استخدام المعدل ? بعد القياس. على سبيل المثال ، يمكنك تغيير .* إلى .*? .

بشكل افتراضي ، لا يدعم grep غير جشعة ، ولكن يمكنك استخدام grep -P لاستخدام بنية Perl.





regex-greedy