विम रेगेक्स में '\ zs' और '\ @ <=' परमाणुओं में क्या अंतर है?


12

यह मुझे दस्तावेज़ीकरण से मिलता है: \zsपूर्ववर्ती रेगेक्स के मिलान के बाद "हाइलाइट किया गया भाग", और \@<=पूर्ववर्ती परमाणु के मिलान के बाद "हाइलाइट किया गया भाग शुरू होता है" । लेकिन मुझे इस की सूक्ष्मता के बारे में ठीक से समझ नहीं है, तो क्या कोई यह समझा सकता है कि कैसे वे गहराई में थोड़ा और भिन्न होते हैं?

यह वही है जो मुझे जिज्ञासु बनाता है: अगर मैं दौड़ता हूं

/\_s\zsnnoremap

अर्थात nnoremapएक स्थान या एक स्टार्ट-ऑफ़-लाइन से पहले का चयन करें (अर्थात पूर्ववर्ती पंक्ति से नई रेखा, इसलिए \_पूर्ववर्ती s) और फिर gnविज़ुअल मोड में प्रवेश करने के लिए दौड़ें और नेत्रहीन अगले मैच का चयन करें , किसी कारण से केवल पहला कॉलम (यानी पहले nमें nnoremap) का चयन किया जाता है - तथ्य यह है कि पूरे के बावजूद nnoremapशब्द है पर प्रकाश डाला साथ :hlsearchचालू कर दिया।

हालांकि, अगर मैं इसके बजाय खोज को चलाता हूं

/\_s\@<=nnoremap

और फिर कोशिश करो gn, पूरी तरह nnoremapसे ठीक से चुना गया है। यहां क्या हो सकता है? क्या मैंने (कुछ कहने की हिम्मत की) कुछ अस्पष्ट बग की खोज की?


मुझे लगता है कि यह :h patternsमेरी स्मृति से पता चलता है कि regexs परमाणुओं से बने होते हैं, अगर यह अंतर समझाने में मदद करता है।
डी। बेन नोबल

जवाबों:


15

ऐसा लगता है कि आपको वास्तव में एक अस्पष्ट बग मिला है। मैंने gn2012 में Vim 7.3 के लिए पाठ्यपुस्तक को वापस लागू किया है। यह मूल रूप से निम्नलिखित तरीके से काम करता है:

1) यह वर्तमान नियमित अभिव्यक्ति के अंतिम मैच के लिए पीछे की ओर खोजता है।

2) यह वर्तमान नियमित अभिव्यक्ति के अगले मैच के लिए आगे की खोज करता है।

यह स्पष्ट करना चाहिए, कि कर्सर अगले मैच की शुरुआत पर होगा, भले ही यह 1 के शुरू में वहां हो)। आखिरकार

3) यह वर्तमान नियमित अभिव्यक्ति के अंत की खोज करता है। और वहाँ कर्सर डालता है।

अब यहां क्या होता है कि वर्तमान मैच के अंत की खोज चारों ओर घूमती है और पिछले मैच के अंत में वापस चली जाती है (क्योंकि wrapscan1 के लिए अक्षम होने के बाद पहले से ही सेट है)। इसके बाद प्रारंभ (बिंदु 2 के अंत) से क्षेत्र के लिए दृश्य मार्कर सेट करता है और क्षेत्र अगले खोज आइटम 3 से स्थानांतरित हो जाता है)।

मैं समस्या पर करीब से नज़र रखूँगा और बाद में विम के लिए एक पैच प्रस्तुत करूँगा।

[अपडेट 22.05.2018] मैंने इस व्यवहार को ठीक करने के लिए एक पैच लिखा और जमा किया है ।

[Update2 22.05.2018] और पैच को पैच स्तर 8.1.0018 के रूप में विलय कर दिया गया है

[अपडेट २२.१०.२०१ ९] विम 22.१.६२ ९ के रूप में तीसरा चरण अब प्रदर्शन नहीं किया गया है। इसके बजाय विम अब मैच की शुरुआत का पता लगा सकता है जब मैच की शुरुआत होगी (चरण 2)


8

क्रिश्चियन ने बुग्गी के व्यवहार के प्रश्न को पूरी तरह से संबोधित किया है gn, लेकिन अभी भी \zsऔर के बीच बुनियादी अंतर हैं \@<=। सबसे बड़ा \@<=एक पूर्ववर्ती परमाणु को संशोधित करता है, जबकि \zsएक परमाणु में है।

विचार करें:

Xnnoremap

\%1cX\zsnnoremap     (regex 1)
\%1cX\@<=nnoremap    (regex 2)
\%2cX\@<=nnoremap    (regex 3)

Regex 1 मैच, चूंकि \%1cस्तंभ 1 से मेल खाता है और वहां एक X है। \zsकेवल X के बाद मैच को फिर से चालू करने का कारण बनता है।

Regex 2 हालांकि मेल नहीं खाता है, क्योंकि \%1cपहला कॉलम मेल खाता है, X\@<=शून्य चौड़ाई (जैसा कि प्रलेखन में उल्लेख किया गया है) और nnoremapकॉलम 2 से शुरू होता है। कॉलम 1 और 2 के बीच स्थिति अंतर बनाने के लिए कुछ भी नहीं है।

nnoremapस्तंभ 2 पर शुरू होने के बाद से रेगेक्स 3 मैच ।


1
मुझे नहीं लगता कि रेगेक्स 2 विफल रहता है क्योंकि कॉलम 1 और 2 के बीच स्थिति अंतर बनाने के लिए कुछ भी नहीं है। अगर यह मुद्दा था, nnoremapतो रेगेक्स से हटाने से एक मैच होगा; लेकिन रेगेक्स अभी भी बिना विफल रहता है। मुझे लगता है कि यह विफल रहता है क्योंकि \%1cX\@<=एक स्थिति को व्यक्त करता है जो मौजूद नहीं हो सकता है। \%1cकॉलम 1 पर स्थिति से मेल खाता है, और इससे पहले मैच के X\@<=लिए एक चरित्र के Xलिए पूछता है। लेकिन पहले कॉलम से पहले कोई भी चरित्र नहीं हो सकता है। यही कारण है कि, भले ही आप Xएक डॉट (किसी भी वर्ण) के साथ प्रतिस्थापित करते हैं, रेगेक्स \%1c.\@<=अभी भी विफल रहता है।
user938271

4

\zsपूरे नियमित अभिव्यक्ति पर लागू होता है, और अगले मैच को पूरे मैच का पहला चरित्र बनाता है। \zsवसीयत से पहले कुछ भी मिलान पाठ के भाग के रूप में शामिल नहीं किया जाएगा।

\@<=दूसरी ओर, केवल परमाणुओं को सीधे इसके चारों ओर प्रभावित करता है, आपको यह निर्दिष्ट करने की अनुमति देता है कि अगला परमाणु केवल तभी मेल खाएगा यदि यह पूर्ववर्ती परमाणु का अनुसरण करता है। इसलिए उदाहरण के लिए, नियमित अभिव्यक्ति:

\vbar.*(foo)@<=bar

के सभी उदाहरणों के बीच के सभी पाठों से मेल खाएंगे bar( उदाहरणों सहित), लेकिन केवल तभी जब दूसरा पूर्ववर्ती हो foo। यानी, यह मेल खाएगा:

barbazfoobar

लेकिन नहीं:

barbazbazbar

\@<=इस तरह से स्थानीयकृत होने के कारण , आप \@<=एकल अभिव्यक्ति में कई बार उपयोग कर सकते हैं :

\vbar.*(foo)@<=bar.*(foo)@<=bar

निम्नलिखित तीन उदाहरणों से मेल खाएगा bar, लेकिन केवल अगर दूसरे दो प्रत्येक पूर्ववर्ती हैं foo

अर्थात दिया गया पाठ:

barfoobarbazfoobar
barfoobarbazbazbar
barbazbarbazfoobar

यह पहली पंक्ति से ही मेल खाएगा।


लेकिन आप के साथ पहली लग रही विनिमय कर सकते हैं \zs, यानी, यह भी काम करना चाहिए \vfoo\zsbar.*(foo)@<=bar:।
कार्ल यंगवे लर्वग

@ KarlYngveLervåg अच्छी बात है। मैंने अंतर स्पष्ट करने के लिए, और उन उदाहरणों का उपयोग करने के लिए संपादित किया है, जहां \zsसब पर प्रतिस्थापित नहीं किया जा सकता है।
रिच

तो, मेरी समझ के लिए, \zsऔर \zeregex पैटर्न के आसपास देखो के साथ बदला जा सकता है, और वे अधिक शक्तिशाली हैं, है ना? अधिक शक्तिशाली कारण उन्हें एक से अधिक बार उपयोग किया जा सकता है और उनके साथ समूहीकृत किया जा सकता है \(\)। और इसलिए भी क्योंकि वे regex के आसपास पर्ल के लुक की तरह काम करते हैं। कुछ भी गलत हुआ?
klaus

1
@क्लास यह मुझे सही लगता है (हालाँकि मैं कोई विशेषज्ञ नहीं हूँ)। ध्यान दें कि आपको उपयोग करना चाहिए \zs/ \zeजब आप कर सकते हैं, हालांकि, क्योंकि वे लुक-अराउंड से अधिक तेज़ हैं।
रिच

समझ लिया। और \zsऔर \zeस्पष्ट रूप से अधिक सहज हैं। स्पष्टीकरण के लिए धन्यवाद।
klaus
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.