प्रत्येक मैच को इंक्रीमेंटिंग काउंटर से कैसे बदला जाए?


14

मैं एक निश्चित पैटर्न की प्रत्येक घटना को एक दशमलव संख्या के साथ खोजना और बदलना चाहता हूं जो 1प्रत्येक मैच के लिए एक-एक करके शुरू होती है ।

मैं इसी तरह के शब्दों वाले प्रश्नों को खोज सकता हूं जो एक काउंटर को बढ़ाने के बारे में नहीं बल्कि प्रत्येक मैच को एक निश्चित राशि द्वारा संशोधित करने के बारे में बताते हैं। अन्य समान प्रश्न एक वृद्धिशील काउंटर के बजाय लाइन नंबर डालने के बारे में हैं।

उदाहरण, इससे पहले:

#1
#1.25
#1.5
#2

उपरांत:

#1
#2
#3
#4

मेरे वास्तविक डेटा में मेरे द्वारा फिर से नंबर करने के लिए आवश्यक सामान के चारों ओर बहुत अधिक पाठ है।


2
अगर आपके पास है perldo, तो आप इस्तेमाल कर सकते हैं:%perldo s/#\K\d+(\.\d+)?/++$i/ge
Sundeep

@ सुदीप: मुझे उल्लेख करना चाहिए कि मैं वेनिला विंडोज 10 पर हूँ, क्षमा करें!
हिप्पिट्रैयल

जवाबों:


15

आपको एक राज्य के साथ प्रतिस्थापन की आवश्यकता है। मुझे याद है कि एसओ पर इस तरह की समस्याओं के लिए (/ कई?) पूरा समाधान उपलब्ध है।

आगे बढ़ने का एक और तरीका है (1)। अब, मैं 2 चरणों में आगे बढ़ूंगा:

  • एक डमी सूची चर जिसे मैं नौकरी करूँगा, गंदे और जटिल चाल के लिए चाहिए
  • एक प्रतिस्थापन जहां मैं इस डमी सरणी के लेन को सम्मिलित करता हूं जिसे मैं प्रत्येक मिलान घटना पर भर रहा हूं।

जो देता है:

:let t=[]
:%s/#\zs\d\+\(\.\d\+\)\=\ze/\=len(add(t,1))/g

यदि आप regexes का उपयोग नहीं कर रहे हैं, तो मैं उपयोग कर रहा हूं :h /\zsऔर \zeयह निर्दिष्ट करने के लिए कि मैं किस उप-पैटर्न से मेल खा रहा हूं, तो मैं संभवतः एक डॉट और अन्य अंकों के बाद अंकों की एक श्रृंखला से मेल खाता हूं। यह किसी भी फ्लोटिंग पॉइंट नंबर के लिए बिल्कुल सही नहीं है, लेकिन यह यहाँ पर्याप्त है।

नोट: आपको इसे एक साधारण इंटरफ़ेस के लिए युगल फ़ंक्शन + कमांड में लपेटना होगा। फिर, एसओ / विम ( यहां , यहां , यहां ) पर उदाहरण हैं आजकल मैं इस चाल को एक कमांड में लपेटने की परवाह नहीं करने के लिए पर्याप्त विम जानता हूं। वास्तव में मैं पहली कोशिश में इस कमांड को लिखने में सक्षम हो जाऊंगा, जबकि मुझे कमांड का नाम याद करने में कई मिनट लगेंगे।


(1) उद्देश्य एक राज्य के बीच प्रतिस्थापन को बनाए रखने में सक्षम होना है, और वर्तमान घटना को कुछ ऐसी स्थिति से बदलना है जो वर्तमान स्थिति पर निर्भर करता है।

हमारे लिए धन्यवाद :s\=एक संगणना के परिणामस्वरूप कुछ सम्मिलित करने में सक्षम है।

राज्य की समस्या को दूर करता है। या तो हम एक फ़ंक्शन को परिभाषित करते हैं जो एक बाहरी राज्य का प्रबंधन कर रहा है, या हम खुद को एक बाहरी स्थिति को अपडेट करते हैं। C (और संबंधित भाषाओं में), हम कुछ का उपयोग कर सकते हैं जैसे length++या length+=1। दुर्भाग्य से, विम स्क्रिप्ट में, +=बॉक्स से बाहर का उपयोग नहीं किया जा सकता है। इसे :setया तो साथ या उसके साथ उपयोग करने की आवश्यकता है :let। इसका मतलब है कि :let length+=1एक संख्या में वृद्धि हुई है, लेकिन कुछ भी वापस नहीं करता है। हम लिख नहीं सकते :s/pattern/\=(length+=1)। हमें कुछ और चाहिए।

हमें म्यूटिंग कार्यों की आवश्यकता है। यानी ऐसे कार्य जो उनके इनपुट को बदल देते हैं। हम setreg(), map(), add()और शायद अधिक। चलो उनके साथ शुरू करते हैं।

  • setreg()एक रजिस्टर को बदल देता है। उत्तम। हम setreg('a',@a+1)@Doktor OSwaldo के समाधान के रूप में लिख सकते हैं। और फिर भी, यह पर्याप्त नहीं है। setreg()एक कार्यविधि की तुलना में अधिक है (हमारे उन लोगों के लिए जो पास्कल, एडा ... जानते हैं)। इसका मतलब यह है कि यह कुछ भी वापस नहीं करता है। दरअसल, यह कुछ लौटाता है। नाममात्र निकास (यानी गैर-अपवादात्मक निकास) हमेशा कुछ वापस करते हैं। डिफ़ॉल्ट रूप से, जब हम कुछ वापस करना भूल जाते हैं, तो 0 लौटाया जाता है - यह अंतर्निहित कार्यों के साथ भी लागू होता है। यही कारण है कि उनके समाधान में प्रतिस्थापन अभिव्यक्ति वास्तव में है \=@a+setreg(...)। मुश्किल है, है ना?

  • map()भी इस्तेमाल किया जा सकता है। यदि हम किसी एकल 0 ( :let single_length=[0]) के साथ एक सूची से शुरू करते हैं , तो हम इसके लिए धन्यवाद बढ़ा सकते हैं map(single_length, 'v:val + 1')। फिर हमें नई लंबाई वापस करने की आवश्यकता है। इसके विपरीत setreg(), map()इसका उत्परिवर्तित इनपुट लौटाता है। यह एकदम सही है, लंबाई सूची में पहले (और अद्वितीय, और इस तरह से पिछले) स्थिति में संग्रहीत है। प्रतिस्थापन अभिव्यक्ति हो सकती है \=map(...)[0]

  • add()एक मैं अक्सर आदत से बाहर है (मैं map()वास्तव में के बारे में सिर्फ हालांकि , और मैं अभी तक उनके संबंधित प्रदर्शन नहीं किया है)। साथ विचार add()वर्तमान स्थिति के रूप में एक सूची का उपयोग करने, और प्रत्येक प्रतिस्थापन से पहले अंत में कुछ संलग्न करने के लिए है। मैं अक्सर सूची के अंत में नए मूल्य को संग्रहीत करता हूं, और प्रतिस्थापन के लिए इसका उपयोग करता हूं। जैसा कि add()इसकी उत्परिवर्तित इनपुट सूची भी लौटाती है, हम उपयोग कर सकते हैं \=add(state, Func(state[-1], submatch(0)))[-1]:। ओपी के मामले में, हमें केवल यह याद रखना होगा कि अब तक कितने मैचों का पता चला है। इस राज्य सूची की लंबाई लौटना पर्याप्त है। इसलिए मेरी \=len(add(state, whatever))


मुझे लगता है कि मैं इसे समझता हूं, लेकिन एक चर के साथ जोड़ की तुलना में सरणी के साथ चाल और इसकी लंबाई क्यों है?
हिप्पिट्रैयल

1
ऐसा इसलिए है क्योंकि \=एक अभिव्यक्ति की उम्मीद है, और क्योंकि सी के विपरीत, i+=1ऐसा कुछ नहीं है जो वेतन वृद्धि करता है और एक अभिव्यक्ति लौटाता है। इसका मतलब यह है कि पीछे \=मुझे एक ऐसी चीज़ की ज़रूरत है जो एक काउंटर को संशोधित कर सके और जो एक अभिव्यक्ति (उस काउंटर के बराबर) लौटाए। अब तक, केवल एक चीज जो मुझे मिली है वह है सूची (और शब्दकोश) हेरफेर कार्य। @Doktor OSwaldo ने एक अन्य म्यूटिंग फ़ंक्शन ( setreg()) का उपयोग किया है । अंतर यह है कि setreg()कभी भी कुछ भी नहीं लौटाया जाता है, जिसका अर्थ है कि यह हमेशा नंबर देता है 0
ल्यूक हर्मिटे

दिलचस्प! आपकी ट्रिक और उसका अनुभव दोनों ही इतने जादुई हैं कि मुझे लगता है कि आपके उत्तर आपके उत्तर में समझाने से लाभान्वित होंगे। मुझे लगता है कि केवल सबसे धाराप्रवाह vimscripters ऐसे अनजाने मुहावरों को जानते होंगे।
हिप्पिट्रैयल

2
@hippietrail। स्पष्टीकरण जोड़ा गया है। मुझे पता है अगर आप और अधिक विशिष्ट स्रोतों की जरूरत है।
11:48 पर ल्यूक हरमिट नाइट

14
 :let @a=1 | %s/search/\='replace'.(@a+setreg('a',@a+1))/g

लेकिन सावधान रहें, यह आपके रजिस्टर को ओवरराइट कर देगा a। मुझे लगता है कि यह आकर्षक के जवाब की तुलना में थोड़ा अधिक सीधा है, लेकिन शायद उसकी गति तेज है। यदि यह समाधान किसी भी तरह से उससे भी बदतर है, तो मैं किसी भी प्रतिक्रिया को सुनना पसंद करूंगा क्योंकि उसका जवाब बेहतर है। जवाब में सुधार करने के लिए किसी भी प्रतिक्रिया की बहुत सराहना की जाएगी!

(यह भी मेरा एसओ उत्तर पर आधारित है /programming/43539251/how-to-replace-finding-words-with-the-different-in-each-occurrence-in-vi-vim -दी / 43539546 # 43539546 )


मैं यह नहीं देखता कि इससे @a+setreg('a',@a+1)छोटा कैसे है len(add(t,1))। अन्यथा, यह एक अच्छा अन्य गंदा चाल है :)। मैं इस एक के हालांकि नहीं है। प्रतिस्थापन पाठ, का एक शब्दकोश परिवर्तनशील समारोह के उपयोग के संबंध :sऔर substitute(), मैं इस का उल्लेख किया है बहुत तेजी से है कि स्पष्ट छोरों - इसलिए lh-vim-lib में मेरी सूची में कार्यों के कार्यान्वयन । मुझे लगता है कि आपका समाधान मेरे बराबर होगा, थोड़ा तेज हो सकता है, मुझे नहीं पता।
ल्यूक हरमिट्टे

2
वरीयताओं के बारे में, मैं एक ही कारण के लिए अपना समाधान पसंद करता हूं: यह @aअसम्बद्ध छोड़ देता है । लिपियों में, यह महत्वपूर्ण IMO है। अंतः-उपयोगकर्ता के रूप में इंटरेक्टिव मोड में रहते हुए, मुझे पता होगा कि मैं किस रजिस्टर का उपयोग कर सकता हूं। एक रजिस्टर के साथ मेसिंग करना कम महत्वपूर्ण है। मेरे समाधान में, इंटरैक्टिव मोड में, एक वैश्विक चर के साथ खिलवाड़ किया गया है; एक स्क्रिप्ट में यह एक स्थानीय चर होगा।
ल्यूक हरमिट 11

@LucHermitte क्षमा करें, मेरा समाधान वास्तव में आप से छोटा नहीं है, मुझे ऐसा बयान लिखने से पहले इसे बेहतर ढंग से पढ़ना चाहिए। मैंने अपने उत्तर से उक्त कथन को हटा दिया है और क्षमा चाहूँगा! आपकी दिलचस्प प्रतिक्रिया के लिए धन्यवाद, मैं इसकी सराहना करता हूं।
डॉकटोर OSwaldo

इसके बारे में चिंता मत करो। रेगेक्स के कारण, यह सोचना आसान है कि टाइप करने के लिए बहुत कुछ है। इसके अलावा, मैं स्वेच्छा से स्वीकार करता हूं कि मेरा समाधान जटिल है। प्रतिक्रिया के लिए आपका स्वागत है। :)
ल्यूक हरमिट

1
वास्तव में तुम कठोर हो। अधिकांश समय मैं एक और जानकारी निकालता हूं जिसे मैं सरणी की अंतिम स्थिति में संग्रहीत करता हूं, जो कि (अंतिम तत्व) है जो मैं अंत में सम्मिलित करता हूं। उदाहरण के लिए, एक के लिए +3, मैं कुछ लिख सकता हूं \=add(thelist, 3 + get(thelist, -1, 0))[-1]
ल्यूक हर्मिटे

5

मुझे एक समान लेकिन अलग-अलग प्रश्न मिले जो मैंने कुछ साल पहले पूछे थे और मैं जो कर रहा था उसे पूरी तरह से समझने के बिना इसके उत्तरों में से एक को बदलने में कामयाब रहा और यह बहुत अच्छा काम कर रहा है:

:let i = 1 | g/#\d\+\(\.\d\+\)\=/s//\=printf("#%d", i)/ | let i = i+1

विशेष रूप से मुझे समझ में नहीं आता है कि मेरा उपयोग %क्यों नहीं किया जाता है या मैं सिर्फ एक सादे चर का उपयोग क्यों करता हूं कि अन्य उत्तर किसी कारण से बचते हैं।


1
वह भी एक व्यवसाय है। मुझे लगता है कि यहां मुख्य नुकसान यह है कि आप प्रति मैच एक स्थानापन्न कमांड का उपयोग करते हैं। तो यह शायद धीमा है। हम एक सादे चर का उपयोग क्यों नहीं करते हैं, इसका कारण यह है कि यह एक सामान्य s//gविवरण में अद्यतन नहीं किया जाएगा । वैसे भी यह एक दिलचस्प समाधान है। हो सकता है @LucHermitte आपको पेशेवरों और विपक्षों के बारे में अधिक बता सकता है, क्योंकि उनकी तुलना में vimscript के बारे में मेरा ज्ञान काफी सीमित है।
डॉकटोर OSwaldo

1
@DoktorOSwaldo। मुझे लगता है कि यह समाधान लंबे समय से काम कर रहा है - printf()हालांकि बिना - के रूप में सूची 7 विम में पेश किए गए थे। लेकिन मुझे मानना ​​होगा कि मुझे उम्मीद नहीं थी (/ याद नहीं था?) <bar>गुंजाइश के दायरे से संबंधित होगा ? :global- IOW, मैं जिस परिदृश्य की उम्मीद कर रहा था :subवह मिलान लाइनों पर लागू करना था , फिर iएक बार बहुत अंत में वेतन वृद्धि । मुझे उम्मीद है कि यह समाधान थोड़ा धीमा होगा। लेकिन क्या वाकई इससे फर्क पड़ता है? महत्वपूर्ण बात यह है कि हम कितनी आसानी से मेमोरी + ट्रायल और एरर से वर्किंग सॉल्यूशन के साथ आ सकते हैं। उदाहरण के लिए, विमगॉल्फर्स मैक्रोज़ पसंद करते हैं।
ल्यूक हर्मिटे

1
@LucHermitte हाँ, मैंने एक ही एक्सेप्ट किया, और कोई गति मायने नहीं रखती। मुझे लगता है कि यह एक अच्छा जवाब है, और मैंने फिर से इससे कुछ सीखा है। शायद g/s//गुंजाइश व्यवहार अन्य गंदी चाल के लिए अनुमति देता है। तो दिलचस्प जवाब और चर्चा दोनों के लिए धन्यवाद, मैं अक्सर जवाब =) देने से उतना नहीं सीखता।
डॉकटोर OSwaldo

4

इस पृष्ठ पर पहले से ही तीन शानदार उत्तर हैं , लेकिन, जैसा कि ल्यूक हरमिट ने एक टिप्पणी में सुझाव दिया है , यदि आप इस ऑफ-द-कफ कर रहे हैं, तो महत्वपूर्ण बात यह है कि आप काम के समाधान पर कितनी जल्दी और आसानी से फिट हो सकते हैं।

जैसे, यह एक ऐसी समस्या है जिसका मैं वास्तव में उपयोग नहीं करूंगा :substitute: यह एक है जिसे नियमित सामान्य मोड कमांड और एक पुनरावर्ती मैक्रो का उपयोग करके आसानी से हल किया जा सकता है:

  1. (यदि आवश्यक हो) पहले, बंद करें 'wrapscan'। हम जिस नियमित अभिव्यक्ति का उपयोग करने जा रहे हैं वह वांछित परिणाम पाठ के साथ-साथ प्रारंभिक पाठ से मेल खाएगा, इसलिए 'wrapscan'मैक्रो अन्यथा हमेशा के लिए वापस खेलना जारी रखेगा। (या जब तक आपको एहसास न हो कि क्या हो रहा है और दबाएं <C-C>।):

    :set nowrapscan
    
  2. अपना खोज शब्द सेट करें (मौजूदा उत्तरों में पहले से बताए गए समान आधार नियमित अभिव्यक्ति का उपयोग करके):

    /#\d\+\(\.\d\+\)\?<CR>
    
  3. (यदि आवश्यक हो) पहले मैच में Nजितनी बार आवश्यकता हो, दबाकर वापस कूदें ,

  4. (यदि आवश्यक हो) पहले मैच को वांछित पाठ में बदलें:

    cE#1<Esc> 
    
  5. "qरजिस्टर साफ़ करें और मैक्रो रिकॉर्ड करना शुरू करें:

    qqqqq
    
  6. वर्तमान काउंटर को खाली करें:

    yiW
    
  7. अगले मैच में कूदें:

    n
    
  8. वर्तमान काउंटर को उसी के साथ बदलें जिसमें हमने अभी-अभी यात्रा की है:

    vEp
    
  9. काउंटर बढ़ाएँ:

    <C-A>
    
  10. स्थूल खेलें q। रजिस्टर "qअभी भी खाली है क्योंकि हमने इसे चरण 5 में मंजूरी दे दी है, इसलिए इस बिंदु पर कुछ भी नहीं होता है:

    @q
    
  11. मैक्रो रिकॉर्ड करना बंद करें:

    q
    
  12. नया मैक्रो खेलें, और देखें!

    @q
    

सभी मैक्रोज़ की तरह, यह बहुत सारे चरणों की तरह दिखता है जब मुझे ऊपर बताया गया है, लेकिन ध्यान दें कि वास्तव में ये टाइप करना मेरे लिए बहुत जल्दी है: इसके अलावा पुनरावर्ती-मैक्रो-रिकॉर्डिंग-बॉयलरप्लेट के अलावा वे सभी नियमित हैं संपादन कमांड मैं संपादन के दौरान हर समय प्रदर्शन कर रहा हूं। केवल कदम जहाँ मैं कुछ भी करने को भी पड़ा सोच चरण 2, जहां मैं नियमित अभिव्यक्ति लिखा खोज करने के लिए किया गया था।

दो कमांड-लाइन मोड कमांड और कीस्ट्रोक्स की एक श्रृंखला के रूप में प्रारूपित, इस प्रकार के समाधान की गति अधिक स्पष्ट हो जाती है: मैं निम्नलिखित बहुत तेजी से जोड़ सकता हूं क्योंकि मैं इसे टाइप कर सकता हूं 1 :

:set nowrapscan
/#\d\+\(\.\d\+\)\?
cE#1<Esc>qqqqqyiWnvEp<C-A>@qq@q

मैं शायद इस पृष्ठ पर अन्य समाधानों के साथ कुछ विचार और प्रलेखन 2 के कुछ संदर्भों के साथ आ सकता था , लेकिन, एक बार जब आप समझते हैं कि मैक्रोज़ कैसे काम करते हैं, तो वे वास्तव में जिस भी गति को आमतौर पर संपादित करते हैं, उस पर मंथन करना आसान है।

1: वहाँ रहे हैं स्थितियों में, जहां मैक्रो अधिक सोचा की आवश्यकता होती है लेकिन, मैं वे व्यवहार में ज्यादा नहीं आते हैं पाते हैं। और आम तौर पर वे परिस्थितियाँ होती हैं जहाँ वे होते हैं जहाँ एक मैक्रो एकमात्र व्यावहारिक समाधान होता है।

2: इसका मतलब यह नहीं है कि अन्य उत्तरदाता आसानी से अपने समाधान के साथ नहीं आ सकते थे: उन्हें बस कौशल / ज्ञान की आवश्यकता होती है जो कि मुझे व्यक्तिगत रूप से मेरी उंगलियों पर इतनी आसानी से नहीं है। लेकिन सभी विम उपयोगकर्ता नियमित संपादन कमांड का उपयोग करना जानते हैं!


1

बस अंत में '#' जोड़कर एक काउंटर 'c'

:let c=0 | g/^#\d\+.*/ let c+=1 | s//\='#' . c

वैश्विक भाग g/^#\d\+.*/ let c+=1हमें काउंटर को केवल उन पंक्तियों में वृद्धि करने की अनुमति देता है जिनके पास एक पैटर्न है


Isipp hippietrails उत्तर में शामिल है?
डी। बेन नोबल

इस मामले में, मुझे लगता है कि मैंने कुछ ऐसा ही करने का एक छोटा तरीका निकाला है, शायद एक टिप्पणी बेहतर होगी।
सर्जियोआराज़ो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.