हटाएँ n लाइनें 1 लाइन स्क्रिप्ट छोड़ें


10

मैं एक मूल विम स्क्रिप्ट बनाना चाहता हूं जो केवल एन लाइनों को हटाती है, 1 पंक्ति को छोड़ती है और दस्तावेज़ के अंत तक दोहराती है। मुझे विशिष्ट मैचों की परवाह नहीं है, मैं सिर्फ लाइन हटाना चाहता हूं। उदाहरण के लिए; इसलिए मैं 3ddjपूरे दस्तावेज़ के लिए कमांड दोहराना चाहता हूं ।

Text I want to keep.   
Text I want to delete.  
Text I want to delete.  
Text I want to delete.  
Text I want to keep.  
Text I want to delete.  
Text I want to delete.  
Text I want to delete.  
Text I want to keep.  
Text I want to delete.  
Text I want to delete.  
Text I want to delete.   

तो ऐसा लगता है ...

Text I want to keep.  
Text I want to keep.  
Text I want to keep.  

धन्यवाद।


आपने regular-expressionअपने प्रश्न पर टैग को शामिल किया है , लेकिन यह प्रश्न नियमित अभिव्यक्ति के साथ ऐसा करने के लिए एक कारण निर्दिष्ट नहीं करता है। यदि आप वास्तव में ऐसी चीज़ की तलाश कर रहे हैं जो नियमित अभिव्यक्तियों का उपयोग करती है, तो stackoverflow.com/questions/17735289/… ब्याज की हो सकती है। यह सवाल नोटपैड ++ के बारे में था, लेकिन जवाब में एक पीसीआर रेगेक्स के अलावा कुछ भी नहीं है। (डिस्क्लेमर: मैंने वह उत्तर लिखा है।)
जैस्पर

अगली बार जब आप कोई प्रश्न पूछते हैं, तो "इसके लिए धन्यवाद" लिखने की कोई आवश्यकता नहीं है। महान समाधान! हर एक जवाब पर। यह तब भी लिखा जाता है जब आप किसी उत्तर पर एक नई टिप्पणी बनाने का प्रयास करते हैं।
पाइप

उसको जोड़ने के लिए, यहाँ प्रशंसा दिखाने का उचित तरीका यह है कि आप के लिए सबसे अच्छा काम करने वाले उत्तर को स्वीकार करें और आपके द्वारा उपयोगी या उपयोगी किसी भी उत्तर को उकेरें। लोग बहुत अधिक बल्कि "धन्यवाद" टिप्पणी की तुलना में देखेंगे।
बी लेयर

जवाबों:


19

बहुत ही सरल दृष्टिकोण:

  1. पहली पंक्ति जिसे आप हटाना चाहते हैं, उस पर जाएँ।
  2. मैक्रो रिकॉर्ड करें: qa3ddjq
  3. इसे उच्च संख्या के साथ दोहराएं: 1000 @ ए

चरण तीन मैक्रो को एक हजार बार दोहराएगा या जब तक कोई त्रुटि सामने नहीं आती है। फ़ाइल का हिटिंग एंड (इसलिए डिलीट करने के लिए कोई लाइन नहीं) एक त्रुटि पैदा करता है और मैक्रो का दोहराव रद्द कर दिया जाता है।

देखते हैं :help recording


2
वह आश्चर्यजनक है!!! बहुत बहुत धन्यवाद, मेरे लिए यह काम किया: डी
मैक्स

1
स्पष्टीकरण: q(कमांड मोड में, और vim या अन्य हाल के वैकल्पिक संस्करणों में [neovim, etc], लेकिन मूल vi में नहीं) का अर्थ है "रिकॉर्डिंग शुरू करें, और इसे 'अगले अक्षर' बफर में डालें"। इसलिए: का qaअर्थ है "एक 'बफर में रिकॉर्डिंग शुरू"। फिर इसके बाद टाइप की गई प्रत्येक कुंजी (जब तक कि qकमांड मोड में) दर्ज नहीं हो जाती है (आप रिकॉर्ड भी कर सकते हैं: एडिट मोड में जा रहे हैं, कुछ टाइपिंग कर रहे हैं, कमांड मोड से बच रहे हैं, आदि)। फिर 12@aजो भी कार्रवाई बफर में दर्ज की गई थी उसे "12 बार" दोहराएगा।
ओलिवियर दुलक

3
इसके अतिरिक्त, यदि आप 1000@qअंत में कुछ चलाना नहीं चाहते हैं, तो आप एक पुनरावर्ती मैक्रो बना सकते हैं: qa3ddj@aq@aहालाँकि, आपको qaqयह सुनिश्चित करने के लिए पहले करना होगा कि "aखाली खाली होना शुरू हो जाए।
जेम्स

17

मेरे लिए सबसे आसान समाधान होगा:

:%norm j3dd

अर्थात्:

  • %: हर लाइन के लिए
  • norm: निम्न कुंजियों को सामान्य मोड में चलाएं
  • j3dd: लाइन पर नीचे जाएं फिर 3 लाइनें हटाएं

तो पहली पंक्ति से, दूसरी पंक्ति पर जाएं और अगली 3 पंक्तियों को हटा दें। दूसरा Text I want to keep.अब दूसरी पंक्ति में है। एक पंक्ति से नीचे जाएं, हटाएं 3. कुल्ला और दोहराएं।


नोट: यदि आप संपूर्ण फ़ाइल को संसाधित नहीं करना चाहते हैं तो आप %normउदाहरण के 5,$normलिए 5 वीं पंक्ति से फ़ाइल के अंत तक की प्रक्रिया को बदल सकते हैं ।


4
बहुत अच्छा विकल्प! Vim में काम करता है (vi नहीं)। मैंने पहले कभी भी "मानक" के बारे में नहीं सुना! (और मैं एक vi [m] geek की तरह हूं)
ओलिवियर दुलैक

6

आपके पास पहले से उपलब्ध कुछ बेहतरीन उपाय हैं। यहाँ एक और एक है:

:g/^/if line('.')%4!=1|:s/^/DELETE ME/|endif
:g/^DELETE ME/d

सबसे पहले, हम हर लाइन (लाइन के शुरू होने के :gखिलाफ मिलान) पर कार्रवाई करते हैं ^और हर लाइन नंबर के लिए परिणाम का प्रदर्शन करते हैं linenumber % 4। यदि परिणाम असमान है 1, तो हम DELETE MEअगले कमांड द्वारा हटाई जाने वाली लाइनों को चिह्नित करते हुए, लाइन की शुरुआत में जोड़ते हैं ।

अगला कमांड एक नियमित ( :g) कमांड है, जो सभी लाइनों से मेल खाता है जो इसके साथ शुरू होता है DELETE MEऔर ऐसा करता है।

ध्यान दें, आप तुरंत पहले :gकमांड का उपयोग करके लाइन को हटा नहीं सकते हैं , क्योंकि इससे परिणामी मोड्यूलो गणना बदल जाएगी और इस तरह, हमें पहले लाइनों को चिह्नित करना होगा और दूसरे चरण में इसे हटाना होगा।


4

मुझे पता है कि यह viचैनल है, लेकिन मेरे लिए यह एक sedसमस्या है।

sed -ne 'p;n;n;n' <file >newfile

तो आप इसे एक viसमाधान में बदल सकते हैं:

:0
!Gsed -ne 'p;n;n;n'

1
एक sed समाधान के लिए +1।
क्रिश्चियन ब्रैबांट

3

एक विकल्प (मुझे लगता है कि हम पंक्ति 1 पर शुरू करते हैं, और उदाहरण के पाठ के अनुसार 2-4, 6-8 और इसी तरह की लाइनें हटाते हैं):

while line(".") < line("$")
    silent +1delete _ 3
endwhile

यदि यह अंतःक्रियात्मक रूप से करना पसंद करते हैं, तो आप "कमांड-लाइन रजिस्टर" का उपयोग कर सकते हैं। वह है, प्रेस

:+1del 3<CR> और फिर 1000@:


1

एक विकल्प: आप किसी भी लाइन को रखना चाहते हैं: 1, 4, आदि। आप इसका उपयोग कर सकते हैं:

awk '!((FNR-1)%3)'  file > newfile
      # awk: when a condition is given without action:
      #        prints the lines for which the condition returns 0.
      # FNR designates the line number in the current file.
      # a%3 : takes the modulus of a and 3. ( 0%3=0, 1%3=1, 2%3=2, 3%3=0, 4%3=1, etc.) 
      # This will be 0 for 3, 6, etc. 
      # But we want it to be 0 (true) for 1, 4, etc : so we substract 1 to NR

# to see that it keeps those lines:
seq 1 20 | awk '!((NR-1)%3)'
1
4
7
10
13
16
19

एक अन्य विकल्प: यदि आप उन पंक्तियों को जानते हैं जो आप चाहते हैं तो कुछ अद्वितीय पैटर्न से मेल खाते हैं:

# for exemple each line you want contains "some pattern":
fgrep "some pattern" file > newfile
# (or regular grep if you want "some pattern" to be interpreted as a regexp)
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.