एक चयन या एक मैच में प्रत्येक पंक्ति में एक वृद्धि संख्या डालें


10

मुझे एक समस्या है जिसे मैं हल करने के लिए दो सामान्य दृष्टिकोणों के बारे में सोच सकता हूं, लेकिन मुझे किसी भी दृष्टिकोण के लिए बारीकियों का पता नहीं है।

...
Level 1:    cũng    also
Level 1:    và      and
Level 1:    như     like; such as
Level 2:    các     plural marker
Level 2:    của     belonging to
...

"लेवल एन" शुरू करने वाली प्रत्येक लाइन के लिए मैं एक नंबर डालना चाहता हूं, जिसकी शुरुआत "01" से है। सादगी के लिए आइए संख्या को बढ़ाएँ।

दृष्टिकोण 1: मैन्युअल रूप से समान स्तर वाली सभी पंक्तियों का चयन करें। जादू सीखो मैं जल्द ही सीखने वाला हूँ।

दृष्टिकोण 2: एक खोज लिखें और प्रतिस्थापित करें जो दिए गए स्तर के साथ सभी पंक्तियों से मेल खाती है जिसमें प्रत्येक मैच में प्रतिस्थापित पाठ में एक संख्या शामिल है, जो प्रत्येक मैच के साथ एक-एक वेतन वृद्धि करता है।

मुझे StackOverflow या अन्य Vim साइटों पर इसी तरह के सवाल मिले हैं, लेकिन प्रत्येक को निम्नलिखित समस्याओं में से एक या अधिक है:

  1. एक मनमाना लेकिन वेतन वृद्धि संख्या के बजाय वर्तमान लाइन नंबर डालने के बारे में है।
  2. संख्या को शून्य-पैड नहीं करता है।
  3. वास्तव में विंडोज 7 पर चलने वाले मेरे विम 7.4 पर चयन के लिए काम नहीं करता है (ये परिणाम त्रुटि में हैं E481: No range allowed।)

मैं mswin.vim के साथ विंडोज में gVim चला रहा हूं, लेकिन एक समाधान जो सभी वेनिला विम पर काम करता है, सेटअप को अनुकूलित किए बिना सबसे अच्छा हो सकता है।


प्रश्न के लिए मैं जो सबसे अच्छा टैग सोच सकता था, वह मौजूद नहीं है: चयन और सीमा फिर से उन टैगों में से एक को टैग करने या बनाने के लिए स्वतंत्र महसूस करते हैं।
हिप्पिएट्रेल

1
यह प्लगइन आपकी समस्या का पूर्ण समाधान नहीं है, लेकिन यह संख्याओं के कॉलम जोड़ने के लिए बहुत उपयोगी है: VisIncrयहां डॉक्स । FWIW।
lcd047

जवाबों:


17

Https://vi.stackexchange.com/a/818/227 पर उत्तर के समान , आप वैश्विक कमांड का उपयोग कर सकते हैं।

इसके साथ आप एक पैटर्न से मेल खाते लाइनों की खोज करने के लिए विम को निर्देश दे सकते हैं, और फिर उस पर कमांड कर सकते हैं।

आपके मामले में, आप "स्तर N:" से शुरू होने वाली लाइनों के लिए पाठ को प्रस्तुत करना चाहते हैं, इसलिए हमारी वैश्विक कमांड हो सकती है

:g/^Level \d:/{COMMANDS}

कमांड के लिए स्थानापन्न कमांड (नियमित अभिव्यक्ति प्रतिस्थापन) का उपयोग करना

आदेश अधिक मजेदार है। मैं आमतौर पर इस तरह से सामान के लिए एक नियमित अभिव्यक्ति प्रतिस्थापन करना पसंद करता हूं, क्योंकि चर का उपयोग करना आसान है।

अपने प्रश्न के लिए उदाहरण

:let i = 1 | g/^Level \d:/s/^/\=printf("%02d ", i)/ | let i = i+1

यह काम किस प्रकार करता है

प्रतिस्थापन कमांड के प्रतिस्थापन खंड में एक अभिव्यक्ति हो सकती है।

पहली चीज़ जो हम करेंगे, वह है एक वेरिएबल iजो शुरुआती संख्या है। मैंने 1 चुना, लेकिन कोई भी संख्या क्या करेगी।let i = 1

फिर हम अपना ग्लोबल कमांड चलाते हैं, जो हमें मैच्योर लाइनों पर एक्शन करने के लिए सेट करता है। g/^Level \d:/

हमारे पास हमारे वैश्विक कमांड में मूल्य और इंसर्बेशन कमांड और लेट कमांड का उपयोग करके हमारे काउंटर को बढ़ाना होगा।s/^/\=printf("%02d ", i)/ | let i = i+1

प्रतिस्थापन कमांड की नियमित अभिव्यक्ति लाइन की शुरुआत का पता ^लगाती है और इसे एक अभिव्यक्ति के साथ बदल देती है, और हमारी अभिव्यक्ति एक स्वरूपित प्रिंट का परिणाम होगी। सी लैंग्वेज की तरह, विम का प्रिंटफ फॉर्मेटिंग पैरामीटर्स लेता है। %02dइसका मतलब है कि एक तर्क को रूपांतरित करें क्योंकि यह एक दशमलव संख्या थी d, जिसमें कम से कम 2 स्थान थे 2और 0 के साथ पैड था 0। विवरण और अन्य रूपांतरण विकल्पों के लिए (फ्लोटिंग पॉइंट फॉर्मेटिंग सहित), देखें :help printf। हम प्रिंटफ को अपना काउंटिंग वैरिएबल देते हैं iऔर यह हमें 01पहली बार, 02दूसरी बार आदि देता है। यह प्रतिस्थापन कमांड द्वारा लाइन की शुरुआत को बदलने के लिए उपयोग किया जाता है, प्रभावी रूप से शुरुआत में प्रिंटफ के परिणाम को सम्मिलित करता है।

ध्यान दें कि मैंने d: के बाद एक स्थान रखा है "%02d "। आपने प्रश्न में यह नहीं पूछा (और मैंने उदाहरण आउटपुट नहीं देखा), लेकिन मुझे संदेह था कि आप शब्द "स्तर" से संख्या को अलग करना चाहते थे। L में लेवल के ठीक बगल में डाले गए नंबर को प्रिंट करने के लिए दिए गए स्ट्रिंग से स्पेस निकालें।

अंत में, वह let i = i + 1प्रत्येक प्रतिस्थापन के बाद हमारे काउंटर को बढ़ाता है।

यह आम तौर पर मनमाने ढंग से कार्यात्मक डेटा के साथ अन्य मानदंडों द्वारा मेल खाने वाली लाइनों के हिस्सों को बदलने के लिए लागू किया जा सकता है।

संयुक्त सामान्य आदेशों का उपयोग करना

यह सरल सम्मिलन या जटिल संपादन के लिए अच्छा है। स्थानापन्न की तरह, हम मिलान करने के लिए वैश्विक का उपयोग करेंगे, लेकिन नियमित अभिव्यक्ति प्रतिस्थापन के बजाय, हम संचालन की एक श्रृंखला निष्पादित करेंगे जैसे कि उपयोगकर्ता द्वारा टाइप की गई हो।

अपने प्रश्न के लिए उदाहरण

:let i = 1 | g/^Level \d:/execute "normal! I" . printf("%02d ", i) | let i = i+1

यह काम किस प्रकार करता है

उपयोग किए गए मान विकल्प के समान हैं (हम इसे अभी भी प्रिंट करने के लिए हमारे नंबर को प्रारूपित करने के लिए उपयोग कर रहे हैं ताकि इसे 2 अंकों के साथ 0 गद्देदार बनाया जा सके), लेकिन ऑपरेशन अलग है।

यहां हम निष्पादित कमांड का उपयोग करते हैं, जो एक स्ट्रिंग लेता है और स्ट्रिंग को पूर्व कमांड ( :help :exe) के रूप में चलाता है । हम एक स्ट्रिंग का निर्माण करते हैं जो हमारे डेटा के साथ "सामान्य!" को जोड़ती है, जो "सामान्य! I01" पहली बार और "सामान्य! I02" दूसरी बार होगा।

normalआदेश प्रदर्शन संचालन के रूप में सामान्य मोड में है। इस उदाहरण में, हमारा सामान्य कमांड है I, जो लाइन की शुरुआत में सम्मिलित होता है। यदि हमने इसका उपयोग किया था तो ddयह लाइन को हटा देगा, oमिलान वाली लाइन के बाद एक नई लाइन खोलेगा। यह ऐसा है जैसे कि आपने Iसामान्य मोड में खुद को टाइप किया (या कोई अन्य ऑपरेशन)। हम प्रयोग !के बाद normalसुनिश्चित करें कि कोई मैपिंग हमारे रास्ते में बनाने के लिए। देख लो :help :normal

फिर क्या डाला जाता है, हमारे प्रिंटफ का मूल्य है, जैसा कि विकल्प का उपयोग करने के पहले उदाहरण में है।

यह विधि regex की तुलना में कट्टर हो सकती है, क्योंकि आप ऐसी चीजें कर सकते हैं execute "normal! ^2wy" . i . "th$p", जो पाठ की शुरुआत में ^जाएंगे, 2 शब्दों को आगे बढ़ाएं 2w, ith 'h' वर्ण तक यैंक y" . i . "th, पंक्ति के अंत तक जाएं $, और पेस्ट करें p

यह लगभग एक मैक्रो को चलाने जैसा है, लेकिन वास्तव में एक रजिस्टर का उपयोग नहीं करता है और किसी भी भाव से तारों को जोड़ सकता है। मुझे यह बहुत शक्तिशाली लगता है।

दृष्टिकोण जहां प्रत्येक स्तर का अपना काउंटर है

आप चाहते हैं कि प्रत्येक स्तर को अपना काउंटर मिल सके। यदि आप समय से पहले अधिकतम स्तर जानते हैं, तो आप निम्न कार्य कर सकते हैं (सबसे बड़ा स्तर खोजने के लिए अतिरिक्त कोड जोड़ना बहुत कठिन नहीं हो सकता है, लेकिन यह उत्तर बहुत लंबा कर देगा। यह तब तक लंबा हो रहा है)।

सबसे पहले, मैं मुक्त कर देता हूं, अगर हम पहले ही इसे पूर्णांक के रूप में उपयोग करते हैं। हम इसे सूची में नहीं बदल सकते, हमें इसे इस तरह से बनाना होगा।

:unlet! i

अगला, आइए मैं एक सूची बनाता हूं जिसमें स्तरों की संख्या होती है। आपने अपने प्रश्न में 2 दिखाए हैं, लेकिन इसके मज़े के लिए 10 मान लेते हैं। चूंकि सूची अनुक्रमण 0 आधारित है, और मैं आपकी सूची की तरह 1 के लिए सही को परेशान नहीं करना चाहता, हम सिर्फ पर्याप्त तत्व (11) बनाएंगे और कभी भी 0 अनुक्रमणिका का उपयोग नहीं करेंगे।

:let j = 0
:let i = []
:while j < 11 | let i += [1] | let j += 1 | endwhile

अगला, हमें स्तर संख्या प्राप्त करने का एक तरीका चाहिए। सौभाग्य से, विकल्प एक फ़ंक्शन के रूप में भी उपलब्ध है, इसलिए हम इसे अपनी लाइन देंगे और स्तर संख्या निकालेंगेsubstitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")

चूंकि अब मैं 11 1एस की सूची (प्रत्येक सूचकांक हमारे स्तर के लिए काउंटर है), हम अब इस प्रतिस्थापन के परिणाम का उपयोग करने के लिए उपरोक्त उदाहरणों में से किसी एक को समायोजित कर सकते हैं:

स्थानापन्न आदेश:

:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | s/^/\=printf("%02d ", i[ind])/ | let i[ind] += 1

सामान्य आदेश:

:unlet! i | unlet! j | let j = 0 | let i = [] | while j < 11 | let i += [1] | let j += 1 | endwhile
:g/^Level \d:/let ind=str2nr(substitute(getline("."), "^Level \\(\\d\\):.*", "\\=submatch(1)", "")) | execute "normal! I" . printf("%02d ", i[ind]) | let i[ind] += 1

उदाहरण इनपुट:

Level 1: stuff

Level 1: Stuff

Some text
Level 3: Other

Level 1: Meh

Level 2: More

उदाहरण आउटपुट:

01 Level 1: stuff

02 Level 1: Stuff

Some text
01 Level 3: Other

03 Level 1: Meh

01 Level 2: More

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

3

आप अपने नंबरों को शून्य पैड तक https://stackoverflow.com/a/4224454/15934 से बना सकते हैं ।

" A reminder: how to start numbers at the first line
:'<,'>s/^\s*\zs/\=(line('.') - line("'<")+1).'. '

लेकिन गद्दी संख्या की कार्रवाई को आसान बनाने के लिए, मैं एक जोड़ी कार्यों और एक कमांड के लिए जाऊंगा:

command!  -range=% -nargs=? PrependNumbers <line1>,<line2>call s:Prepend(<args>)

function! s:ReplExpr(nb_digits, number)
  return repeat('0', a:nb_digits - strlen(a:number)).a:number
endfunction

function! s:Prepend(...) range
  let pattern = a:0 > 0 ? '\ze'. a:1 : '^'
  let nb_values = (a:lastline - a:firstline) + 1
  let nb_digits = strlen(nb_values)
  exe ':'.a:firstline.','a:lastline.'s#'.pattern.'#\=s:ReplExpr(nb_digits, 1+ line(".")-'.a:firstline.')." "#'
endfunction

थान, अपनी लाइनों का चयन करें और टाइप करें :PrependNumber(आप देखेंगे :'<,'>PrependNumber। [नोट: कमांड एक वैकल्पिक पैरामीटर लेता है: वह पैटर्न जिसके पहले नंबर डाला जाएगा]


लेकिन इसका line(".")मतलब यह नहीं है कि "वर्तमान लाइन नंबर का उपयोग करें"? यह मेरी समस्या थी 1. पिछले उत्तरों के साथ मैं पा सकता था।
हिप्पिएट्रेल

1
हाँ यही है। इसलिए मैं रेंज में पहली पंक्ति की लाइन संख्या को घटाता हूं।
ल्यूक हरमिट्टे

आह ठीक है, मैंने अभी तक इसका परीक्षण नहीं किया है क्योंकि मुझे यह भी याद नहीं है कि विम में एक स्क्रिप्ट कैसे दर्ज की जाए ... उस पर पहले पढ़ा (-:
hippietrail

1
जैसा कि आप विंडोज़ के अंतर्गत हैं, कोड को कॉपी पेस्ट करें $HOME/vimfiles/plugin/whatevernameyouwish.vim। या यहां तक ​​कि आपके $HOME/_vimrc(विंडोज़ फ़ाइल नाम) यदि आपकी पसंद (पहली बार में)। यदि आप सुनिश्चित नहीं हैं कि आपकी मशीन पर $ HOME क्या है, तो विम से पूछें कि वह क्या सोचता है ->:echo $HOME
Luc Hermitte

1
:sourceअगर लिपि को सही निर्देशिका ({rtp} / plugin], या {rtp} / ftplugin / {filetype} / ftplugin में filetype विशिष्ट प्लगइन्स) के लिए ठीक से स्थापित किया गया है, तो आपको इसकी आवश्यकता भी नहीं है । :sourceवह है जो हमें डेढ़ दशक पहले खेलना था।
ल्यूक हेर्मिटेट

2

आप इसे मैक्रो रिकॉर्ड करके देख सकते हैं। अपनी मूल फ़ाइल से शुरू करते हुए, संख्या के साथ पहला उदाहरण प्रस्तुत करें।

01 Level 1:    cũng    also
Level 1:    và      and
Level 1:    như     like; such as
Level 2:    các     plural marker
Level 2:    của     belonging to

अपने कर्सर को 01इसके साथ ले जाएँ , चुनें और इसे yank करें yiw। अब आप इस बिंदु से अपने कार्यों को रिकॉर्ड करना चाहते हैं।

qq/^Level 1<CR>P<C-A>A<space><esc>0yiwq

  • qq रजिस्टर q में मैक्रो शुरू करें
  • /^Level 1<CR> "स्तर 1" से शुरू होने वाली रेखा के लिए खोजें
  • P कर्सर से पहले पेस्ट करें (जिसमें आपका नंबर हो)
  • <C-A> संख्या बढ़ जाती है
  • A<space><esc> नंबर के बाद स्पेस डालें
  • 0 शुरू करने के लिए ले जाएँ
  • yiw वर्तमान संख्या को दें
  • q मैक्रो को समाप्त करें

फिर इस मैक्रो का उपयोग करके दोहराएं @q


1
है <C-A>एक + नियंत्रण? यह विंडोज पर विम में सब कुछ का चयन करता है।
हिप्पिट्रैएल

यह कंट्रोल + ए है। विम में यह संख्या बढ़ाना चाहिए। यदि आपने Vim क्रियाओं के बजाय Windows क्रियाओं को करने के लिए अपनी कीबाइंडिंग को बदल दिया है, तो आपका अधिकांश वह काम नहीं हो पाएगा जो लोग यहाँ पोस्ट करते हैं।
jecxjo

विंडोज का कोई भी संस्करण किसी के असीम ज्ञान के कारण अलग-अलग बाइंडिंग के साथ नहीं आता है। मैं सिर्फ वेनिला आउट-ऑफ-द-बॉक्स बाइंडिंग का उपयोग कर रहा हूं। मैंने बीस वर्षों में कभी भी एक विम कुंजी को नहीं बदला है, जिसे मैं याद कर सकता हूं (-:
हिप्पिट्रिल

ऐसा नहीं होना चाहिए, मेरे विंडोज इंस्टाल में सामान्य विम बाइंडिंग हैं। क्या यह संभव हो सकता है कि आप किसी और के निर्माण को स्थापित करें? या आप "आसान" मोड में विम चला सकते हैं? मेरा मानना ​​है कि विंडोज़ सामान्य और आसान मोड विकल्पों के साथ डेस्कटॉप आइकन स्थापित करती है।
jecxjo

3
नहीं, इसका कारण यह है कि विंडोज़ में डिफ़ॉल्ट इंस्टॉल mswin.vim को लोड करता है। यदि आप अपना खुद का vimrc बनाते हैं और mswin.vim को लोड नहीं करते हैं तो आपको सामान्य vim बाइंडिंग मिलती है। मैं अपने सभी इंस्‍टॉल (लिनक्स, मैक और विंडोज) के लिए एक ही vimrc रखता हूं और mswin.vim के साथ कभी भी डील नहीं करता। इस मुद्दे पर अधिक जानकारी के लिए देखें stackoverflow.com/questions/289681/…
jecxjo
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.