लाइनों के क्रम को उल्टा कैसे करें?


24

मैं लाइनों के क्रम को कैसे उल्टा कर सकता हूं ताकि पहली पंक्ति अंत में दिखाई दे और अंतिम पंक्ति पहले दिखाई दे? (एक बफर, एक पता सीमा, या एक लाइन दृश्य मोड चयन में सभी लाइनें हो सकती हैं।)

मैं रूपांतरित करना चाहूंगा

rat
ox
tiger
⋮
dog
pig

में

pig
dog
⋮
tiger
ox
rat

जैसे बाहरी आदेश का सहारा लिए बिना tac


इस सवाल पर बेहतर टैग के लिए कोई सुझाव?
२००/२ 200

1
शायद एक नया 'शुद्ध-vi' या इसी तरह का टैग? मैंने कई प्रश्न देखे हैं जो एक ऐसे टैग से लाभान्वित होंगे जो किसी बाहरी उपकरण को शामिल करने की इच्छा का संकेत देगा। क्या मुझे मेटा के बारे में पूछना चाहिए?
जॉन ओ.एम.

1
@Carpetsmoker (और किसी और को भी इसका अनुसरण करने में दिलचस्पी है) टैग सवाल अब मेटा मेटा. vi.stackexchange.com/questions/1229/…
John O'M पर है।

जवाबों:


29

वैश्विक शक्ति यहां काम करेगी:

:g/^/exe "normal ddggP"

या, और अधिक सरल (धन्यवाद @tommcdo)

:g/^/move 0

पहले हर पंक्ति से मेल खाएगा और प्रत्येक पंक्ति के लिए, इसे हटा दें और इसे फ़ाइल के शीर्ष पर चिपकाएँ। जैसे ही यह फ़ाइल के माध्यम से आगे बढ़ता है, यह पाठ को उलट देता है।

इसी तरह दूसरी हर पंक्ति से मेल खाती है और इसे फ़ाइल के शीर्ष पर ले जाती है।

नोट: ये दोनों पूरी फाइल पर काम करते हैं और लाइनों के एक सबसेट को उलटने के लिए सही तरीके से लागू नहीं होंगे। एक सीमा के भीतर काम करने वाले समाधान के लिए इंगो कर्कट का उत्तर देखें ।

विवरण:

gवैश्विक कमांड
/^/किसी भी रेखा से मेल खाता है जिसमें एक शुरुआत है (यानी सभी लाइनें)
exeनिम्नलिखित स्ट्रिंग
"normalनिष्पादित करें सामान्य मोड कमांड करें वर्तमान स्थिति के साथ फ़ाइल पेस्ट के शीर्ष पर
ddलाइन
ggहटाई जाएं
P

move 0 वर्तमान लाइन को नीचे की रेखा 0 पर ले जाता है (जो इसे स्थिति 1 पर रखता है, या फ़ाइल की पहली पंक्ति है)


6
:normalकमांड के बजाय , हम एक्स कमांड का उपयोग कर सकते हैं :move 0, जो लाइन को बफर की शुरुआत में ले जाता है।
tommcdo

1
यह :executeभी केवल तभी आवश्यक है जब कमांड को गतिशील रूप से निर्मित करने की आवश्यकता हो, जैसे :execute 'normal' g:user_command
tommcdo

@tommcdo अच्छे अंक! मैं उपयोग करने की आदत में :executeहूं क्योंकि मैं अक्सर मौजूदा एक्स के बाद अन्य पूर्व कमांड को लागू करता हूं, और यह मेरे लिए :exeपहले से ही वापस जाने और बाद में डालने की तुलना में अधिक सुविधाजनक है । दुर्भाग्य से, यह आदत इस उत्तर में लीक हो गई जहां यह उतना लागू नहीं होता है।
जॉन ओ.एम.

1
मेरे उपयोग के बारे में अधिक स्पष्टीकरण :execute: चूंकि यह एक स्ट्रिंग लेता है, यह एक स्पष्ट परिसीमन प्रदान करता है, जहां सामान्य-मोड कमांड समाप्त होते हैं, भले ही मैं स्ट्रिंग का निर्माण नहीं कर रहा हूं, मेरे लिए संतुलित उद्धरण चिह्नों को ढूंढना आसान है। <esc>या मोड को समाप्त करने के लिए जो भी हो। फिर, यह व्यक्तिगत प्राथमिकता और आदत है। :-)
जॉन ओ'एम।

3
यह एक सीमा btw के लिए काम करेगा: :9,11g/^/move 8... अंतिम संख्या की सीमा 1 माइनस 1 (इंगो के उत्तर से अनुकूलित) की शुरुआत होनी चाहिए।
मार्टिन टूरनोइज

13

यह एक-लाइनर (आपके लिए ~/.vimrc) एक :Reverseकमांड को परिभाषित करता है ; आप :globalसीधे भाग का उपयोग भी कर सकते हैं, लेकिन :move(जो कि पुनरावृत्ति की सीमा से पहले लाइनों को स्थानांतरित करता है, जिससे इसका उल्टा हो जाता है) का सिंटैक्स याद रखना आसान नहीं है:

:command! -bar -range=% Reverse <line1>,<line2>global/^/m<line1>-1

1
पाठकों के लिए FYI के रूप में, <line1>& <line2>को एक सीमा पर इस कार्य को करने की आवश्यकता होती है, अर्थात: :7,9Reverse(वे की विशेषताएँ हैं command, नहीं globalया नहीं move)। सरल :command! -bar -range=% Reverse :global/^/m 0भी काम करेगा, लेकिन केवल पूरे बफर के लिए ...
मार्टिन Tournoij

6

शुद्ध विम:

:g/^/m0

स्पष्टीकरण:

के अनुसार :help multi-repeat, :gऔर इसके चचेरे भाई :vदो-पास तरीके से काम करते हैं।

:gहर पंक्ति के मिलान का पहला पास {pattern}, जबकि दूसरा पास (जाहिरा तौर पर फ़ाइल की शुरुआत में शुरू हुआ और अंत तक आगे बढ़ना) प्रदर्शन करता है [cmd]। उपर्युक्त उपयोग :gउस आदेश का लाभ उठाता है जिसमें लाइनों को संसाधित किया जाता है (जो संभवतः ठीक है, हालांकि तकनीकी रूप से गारंटी नहीं है)।

यह पहले हर लाइन को चिन्हित करके काम करता है, फिर पहली चिह्नित लाइन को फाइल के शीर्ष पर ले जाता है, फिर दूसरे को फाइल के शीर्ष पर ले जाता है (लाइन से पहले ऊपर ले जाया गया है), फिर तीसरी चिह्नित लाइन (फिर से पहले की गई ऊपर की तरफ जाती है) लाइन), और इसी तरह जब तक फ़ाइल में अंतिम पंक्ति शीर्ष पर नहीं जाती है, प्रभावी रूप से फ़ाइल को उलट देती है।

ध्यान दें कि यदि :gऊपर से नीचे तक के अलावा किसी भी क्रम में संसाधित लाइनें, यह आदेश काम नहीं करेगा।

स्रोत: vim wikia पर सभी लाइनों और की शक्ति का उलटा

बाहरी आदेशों का उपयोग करने वाले कुछ उदाहरण:

  • tac( GNU कोरुटिल्स का हिस्सा - catउलट)

    :%!tac                                                                                                                                                                                                                                                              
    
  • tail BSD / OSX पर (POSIX- अनुरूप नहीं):

    :%!tail -r
    

    -r -R विकल्प इनपुट को रिवर्स ऑर्डर में प्रदर्शित करता है, लाइन द्वारा।

    man tarअधिक विवरण के लिए जाँच करें ।

अधिक विचारों के लिए, देखें:


2
जॉन के जवाब :g/^/m0के समान नहीं :g/^/move 0है?
मूरू

@ ममरू मुझे ऐसा लगता है, लेकिन यह छोटा है (विम विकिया के अनुसार) और मैंने कमांड लाइनों का उपयोग करने के कुछ अतिरिक्त उदाहरणों के साथ अलग-अलग स्पष्टीकरण जोड़ा है।
kenorb

हां, मैंने अन्य आदेशों के कारण अपवित्र किया (मैं भी पोस्ट करने आया था tac)। लेकिन मुझे संदेह है कि उत्तर को दोहराया जाने के कारण डाउनवोट था।
मूरू

मुझे पता है कि tacओपी द्वारा उल्लेख किया गया था, लेकिन अन्य सभी समान प्रश्न इस तरह से नकली होंगे, इसलिए इसे फिर से उल्लेख करना अच्छा है। जॉन ने इस cmd को @tommcdo टिप्पणी से लिया है, मैंने इसे शुरुआत में DerMike से लिया है , लेकिन मुझे लगता है कि उन्होंने इसे बस विकिया से लिया था, इसलिए मैंने विकिया को क्रेडिट दिया है, इसलिए यह पूरी तरह से डुप्लिकेट नहीं है क्योंकि स्पष्टीकरण पूरी तरह से अलग है।
kenorb

यह अधिक मूल्य जोड़ता है, क्योंकि यह उचित स्पष्टीकरण के साथ बहुत कम संस्करण है और मैं सही स्रोतों को भी श्रेय दे रहा हूं। शेल कमांड का उपयोग करना बहुत सरल और सुविधाजनक है। अगर लोग सहमत नहीं हैं, तो वे बस वोट डाउन कर सकते हैं, कोई बड़ी बात नहीं।
kenorb

6

कार्यात्मक विम की भावना में:

:call setline(1, reverse(getline(1, line('$'))))
  • getline(1, line('$'))बफर में सभी लाइनों की एक सूची देता है। '$'एक विशेष तर्क है line()जिसके लिए बफर में अंतिम पंक्ति इंगित करता है।
  • reverse(...)इनपुट सूची को उलट देता है, इन-प्लेस। reverse(copy(...))यदि इनपुट सूची को संशोधित नहीं किया जाना चाहिए, तो एक का उपयोग करने की आवश्यकता होगी ।
  • setline(1, ...)दूसरे तर्क के साथ निर्दिष्ट पंक्ति को बदलता है। जब दूसरा तर्क एक सूची है, तो सूची की लंबाई के समान पंक्तियों को सूची की सामग्री से बदल दिया जाता है।

यदि आप चाहें, तो आप एक कमांड को भी परिभाषित कर सकते हैं जो एक सीमा लेता है (डिफ़ॉल्ट %संपूर्ण बफर)

:command! -bar -range=% Reverse call setline(<line1>, reverse(getline(<line1>, <line2>)))

1
मुझे यह उत्तर पसंद है। यह सामान को हाइलाइट नहीं करता है (यदि hlsearchसक्षम है) :g/अन्य उत्तरों से कमांड की तरह ... प्रदर्शन शायद खराब है, हालांकि? चूंकि यह getline(1, line('$'))मेमोरी में पूरे बफर को प्राप्त करता है। reverse()जगह-जगह लगता है, इसलिए इस तरह से बहुत कम मेमोरी लेनी चाहिए ...
मार्टिन टूरनोइज

3

प्रति दस्तावेज प्रलेखन usr_12.txt - चतुर चाल

12.4 लाइन क्रम उल्टा

:globalकमांड के साथ जोड़ा जा सकता है :move, पहली पंक्ति से पहले सभी लाइनों को स्थानांतरित करने के लिए एक उलट फ़ाइल में जिसके परिणामस्वरूप आदेश। आदेश है:

:global/^/m 0

संक्षिप्त:

:g/^/m 0

^नियमित अभिव्यक्ति लाइन (भले ही लाइन खाली है) की शुरुआत से मेल खाता है। :moveआदेश, पौराणिक zeroth पंक्ति के बाद करने के लिए मिलान लाइन ले जाता है तो वर्तमान मिलान लाइन फ़ाइल की पहली पंक्ति हो जाता है। चूंकि :globalकमांड बदलती लाइन नंबरिंग से भ्रमित नहीं :globalहोती है, फ़ाइल की सभी शेष लाइनों से मेल खाने के लिए आगे बढ़ती है और प्रत्येक को पहले की तरह लगाती है।

यह भी कई लाइनों पर काम करता है। पहले पहली पंक्ति के ऊपर जाएं और इसे चिह्नित करें mt। फिर कर्सर को रेंज में अंतिम लाइन पर ले जाएं और टाइप करें:

:'t+1,.g/^/m 't

1

सापेक्ष संख्याओं का उपयोग करना। अनुच्छेद 13 पंक्ति में शुरू होता है और अधिक 4 पंक्तियों तक फैला होता है

 :13,13+4g/^/m12
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.