लगातार सभी डुप्लिकेट हटाएं


13

मेरे पास एक फाइल है जो इस तरह दिखती है।

Move to 230.00
Hold
Hold
Hold
Hold
Hold
Hold
Move to 00.00
Hold 
Hold 
Hold 
Hold 
Hold 
FooBar
Hold 
Spam
Hold

मैं इसे इस तरह देखना चाहूंगा:

Move to 230.00
Hold
Move to 00.00
Hold 
FooBar
Hold
Spam
Hold

मुझे यकीन है कि कोई ऐसा तरीका होना चाहिए जो विम जल्दी से ऐसा कर सकता है, लेकिन मैं अपने सिर को चारों ओर कैसे लपेट नहीं सकता। क्या यह मैक्रोज़ की शक्ति से परे है, और उन्हें वैंपस्क्रिप्ट की आवश्यकता है?

इसके अलावा, यह ठीक है अगर मुझे "होल्स" के प्रत्येक ब्लॉक में एक ही मैक्रो लागू करना है। यह एक एकल मैक्रो नहीं है जिसे पूरी फ़ाइल मिलती है, हालांकि यह बहुत बढ़िया होगा।

जवाबों:


13

मुझे लगता है कि निम्नलिखित कमांड को काम करना चाहिए:

 :%s/^\(.*\)\(\n\1\)\+$/\1/

स्पष्टीकरण:

हम परिवर्तन के लिए पूरी फ़ाइल पर प्रतिस्थापन आदेश का उपयोग patternमें string:

:%s/pattern/string/

यहाँ patternहै ^\(.*\)\(\n\1\)\+$और stringहै \1

pattern इस तरह तोड़ा जा सकता है:

^\(subpattern1\)\(subpattern2\)\+$

^और $क्रमशः लाइन की शुरुआत और लाइन के अंत से मेल खाते हैं।

\(और \)इसका उपयोग संलग्न करने के लिए किया जाता है subpattern1ताकि हम इसे बाद में विशेष संख्या से संदर्भित कर सकें \1
उन्हें संलग्न करने के लिए भी उपयोग किया जाता है subpattern2ताकि हम इसे 1 या उससे अधिक बार परिमाणक के साथ दोहरा सकें \+

subpattern1है .*
.नई लाइन को छोड़कर किसी भी चरित्र से मेल खाता हुआ metacharacter है और *एक परिमाणक कि पिछले चरित्र 0, 1 या अधिक बार से मेल खाता है।
इसलिए बिना .*किसी नई पंक्ति के किसी भी पाठ से मेल खाता है।

subpattern2है \n\1
\nएक नई लाइन से मेल खाता है और \1एक ही पाठ कि अंदर पहले मिलान किया गया था से मेल खाता है \(, \)यहाँ जो है subpattern1

तो patternइसे इस तरह से पढ़ा जा सकता है:
पंक्ति की एक शुरुआत ( ^) के बाद कोई भी नई पंक्ति नहीं है ( .*) के बाद एक नई पंक्ति ( \n) और फिर एक ही पाठ ( \1), बाद के दो को एक या अधिक बार दोहराया जा रहा है ( \+), और अंत में लाइन का अंत ( $)

जहां भी patternमिलान किया जाता है (समान लाइनों का एक ब्लॉक), प्रतिस्थापन कमांड इसे बदल देता है जिसके साथ stringयहां \1(ब्लॉक की पहली पंक्ति) है।

यदि आप यह देखना चाहते हैं कि आपकी फ़ाइल में कुछ भी बदले बिना लाइनों के कौन से ब्लॉक प्रभावित होंगे, तो आप hlsearchविकल्प को सक्षम कर सकते हैं और nकमांड के अंत में प्रतिस्थापन ध्वज जोड़ सकते हैं :

:%s/^\(.*\)\(\n\1\)\+$/\1/n

अधिक दानेदार नियंत्रण के लिए, आप cप्रतिस्थापन ध्वज को जोड़ने के बजाय लाइनों के प्रत्येक ब्लॉक को बदलने से पहले एक पुष्टिकरण के लिए पूछ सकते हैं :

:%s/^\(.*\)\(\n\1\)\+$/\1/c

प्रतिस्थापन आदेश पढ़ने के बारे में अधिक जानकारी के लिए :help :s,
प्रतिस्थापन झंडे के लिए :help s_flags,
विभिन्न अक्षरों से परे और परिमाणकों के लिए पढ़ने के लिए :help pattern-atoms,
और के लिए vim में रेगुलर एक्सप्रेशन को पढ़ने के इस

संपादित करें: वाइल्डकार्ड ने कमांड $के अंत में एक समस्या को ठीक किया pattern

इसके अलावा ब्लडगैन का एक ही कमांड का एक छोटा और अधिक पठनीय संस्करण है।


1
अच्छा; $हालाँकि, इसमें आपकी कमांड की जरूरत है । अन्यथा यह एक पंक्ति के साथ अप्रत्याशित चीजें करेगा जो पिछली पंक्ति के समान पाठ से शुरू होता है , लेकिन कुछ अन्य अनुगामी अक्षर हैं। यह भी ध्यान दें कि आपके द्वारा दिया गया मूल कमांड कार्यात्मक रूप से मेरे उत्तर के बराबर है :%!uniq, लेकिन हाइलाइट और कन्फर्मेशन फ्लैग अच्छे हैं।
वाइल्डकार्ड

आप सही हैं, मैंने अभी जाँच की है और यदि डुप्लिकेट लाइनों में से एक में एक अलग अनुगामी चरित्र होता है, तो कमांड अपेक्षित व्यवहार नहीं करता है। मुझे नहीं पता कि इसे कैसे ठीक करना है, परमाणु \nरेखा के अंत से मेल खाता है और इसे रोकना चाहिए लेकिन यह नहीं करता है। मैंने बिना किसी सफलता के साथ $बस जोड़ने की कोशिश की .*। मैं कोशिश कर रहा हूं और इसे ठीक करूंगा, लेकिन अगर मैं नहीं कर सकता, तो शायद मैं अपना जवाब हटा दूंगा या अंत में चेतावनी जोड़ दूंगा। इस समस्या को इंगित करने के लिए धन्यवाद।
saginaw

1
कोशिश करें:%s/^\(.*\)\(\n\1\)\+$/\1/
वाइल्डकार्ड

1
आपको यह विचार करना चाहिए कि स्ट्रिंग के$ अंत से मेल खाता है , रेखा के अंत से नहीं। यह तकनीकी रूप से सच नहीं है - लेकिन जब आप कुछ अपवादों के अलावा इसके बाद वर्ण डालते हैं, तो यह किसी विशेष चीज़ के बजाय शाब्दिक रूप से मेल खाता है । इसलिए मल्टी-लाइन मैचों के लिए उपयोग करना बेहतर है। (देखें )$\n:help /$
वाइल्डकार्ड

मुझे लगता है कि आप सही हैं कि \nरेगेक्स के अंदर कहीं भी इस्तेमाल किया जा सकता है जबकि $संभवतः इसका उपयोग केवल अंत में किया जाना चाहिए। बस दोनों के बीच अंतर करने के लिए, मैंने \nएक नई $पंक्ति से मेल खाने वाले उत्तर को संपादित किया है (जो सहज रूप से आपको लगता है कि कुछ पाठ अभी भी है) जबकि रेखा के अंत से मेल खाता है (जिससे आपको लगता है कि कुछ भी नहीं है बाएं)।
धनु नवा

10

निम्नलिखित का प्रयास करें:

:%s;\v^(.*)(\n\1)+$;\1;

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

  1. विम हमें हमारे मैच को बदलने / / झंडे के पाठ को विभाजित करने के लिए बैकस्लैश ( \ ), डबल-कोट ( " ), या पाइप ( ! ) को छोड़कर किसी भी गैर-अल्फ़ान्यूमेरिक एएससीआईआई चरित्र का उपयोग करने देता है । यहां, मैंने सेमीकोलन ( ; ) का चयन किया , लेकिन आप कर सकते हैं दूसरा चुनें।
  2. विम नियमित अभिव्यक्तियों के लिए "जादू" सेटिंग्स प्रदान करता है, ताकि बैकस्लैश से बचने के बजाय पात्रों को उनके विशेष अर्थों के लिए व्याख्या की जाए। यह वाचालता को कम करने के लिए सहायक है, और क्योंकि यह "नाममात्र" डिफ़ॉल्ट की तुलना में अधिक सुसंगत है। के साथ शुरू \vअर्थ है "बहुत जादू," या के अलावा सभी पात्रों अल्फान्यूमेरिक ( एक-Z0-9 ) और अंडरस्कोर ( _ ) विशेष अर्थ नहीं होता।

घटकों के अर्थ हैं:

पूरी फ़ाइल के लिए %

एस विकल्प

; स्थानापन्न स्ट्रिंग शुरू करो

\ v "बहुत जादू"

^ लाइन की शुरुआत

(*।) 0 या किसी वर्ण का अधिक (समूह 1)

(\ n \ 1) + न्यूलाइन उसके बाद (समूह 1 मैच पाठ), 1 या अधिक बार (समूह 2)

लाइन का $ अंत (या इस मामले में, लगता है कि अगला चरित्र एक नई पंक्ति होना चाहिए )

; स्ट्रिंग की जगह शुरू करें

\ 1 समूह 1 मैच पाठ

; कमांड का अंत या झंडे शुरू करना


1
मैं वास्तव में अपने जवाब की तरह है, क्योंकि यह अधिक पठनीय है बल्कि इसलिए भी कि इसे बनाया मुझे बेहतर के बीच अंतर समझना \nऔर $\nपैटर्न में कुछ जोड़ता है: वर्ण नई लाइन जो विम को बताती है कि निम्नलिखित पाठ एक नई लाइन पर है। जबकि $पैटर्न में कुछ भी नहीं जोड़ा जाता है, यह केवल एक मैच के लिए मना किया जाता है अगर पैटर्न के बाहर का अगला वर्ण नई लाइन नहीं है। कम से कम, यह वही है जो मैंने आपके उत्तर को पढ़कर समझा है और :help zero-width
saginaw

और उसी के लिए सच होना चाहिए ^, यह पैटर्न में कुछ भी नहीं जोड़ता है, यह सिर्फ एक मैच को रोकता है अगर पैटर्न के बाहर का पिछला चरित्र नई लाइन नहीं है ...
14

@saginaw आपके पास यह बिल्कुल सही है, और यह एक अच्छी व्याख्या है। नियमित अभिव्यक्तियों में, कुछ वर्ण नियंत्रण पात्रों के रूप में हो सकते हैं । उदाहरण के लिए, +"पूर्ववर्ती अभिव्यक्ति (चरित्र या समूह) 1 या अधिक बार दोहराएं , " का अर्थ है, लेकिन खुद से कुछ भी मेल नहीं खाता है। ^इसका मतलब है "स्ट्रिंग के बीच में शुरू कर सकते हैं नहीं" और $इसका मतलब है "स्ट्रिंग के बीच में समाप्त नहीं हो सकता।" ध्यान दें मैंने "लाइन" नहीं कहा, लेकिन वहां "स्ट्रिंग"। विम प्रत्येक लाइन को डिफ़ॉल्ट रूप से एक स्ट्रिंग के रूप में मानता है - और यही वह जगह \nहै जहाँ यह अंदर आता है। यह विम को इस मैच को बनाने की कोशिश करने के लिए एक नई लाइन का उपभोग करने के लिए कहता है।
ब्लडगैन

8

यदि आप सभी आसन्न समान रेखाओं को हटाना चाहते हैं, तो बस नहीं Hold, आप इसे बाहरी फ़िल्टर से बहुत आसानी से कर सकते हैं vim:

:%!uniq (एक यूनिक्स वातावरण में)।

यदि आप इसे सीधे में करना चाहते हैं, तो यह vimवास्तव में बहुत मुश्किल है। मुझे लगता है कि एक तरीका है, लेकिन सामान्य मामले के लिए इसे 100% कार्यात्मक बनाने के लिए बहुत मुश्किल है और मैंने अभी तक सभी बगों पर काम नहीं किया है।

हालाँकि, इस विशिष्ट मामले के लिए, क्योंकि आप नेत्रहीन देख सकते हैं कि अगली पंक्ति जो नॉन-डुप्लिकेट है, उसी वर्ण से शुरू नहीं होती है, आप यह कर सकते हैं:

:+,./^[^H]/-d

+वर्तमान लाइन के बाद लाइन का मतलब है। द। वर्तमान लाइन को संदर्भित करता है। /^[^H]/-पहले लाइन का मतलब है ( -) अगली लाइन जो H से शुरू नहीं होती है।

फिर डी हटा है।


3
जबकि स्थानापन्न और वैश्विक uniqवीआईएम कमांड अच्छा अभ्यास है, कॉलिंग (या तो विम के भीतर से या शेल का उपयोग करके) मैं इसे कैसे हल करूंगा। एक बात के लिए, मुझे पूरा यकीन है uniqकि वे लाइनें होंगी जो रिक्त हैं / सभी रिक्त स्थान समतुल्य हैं (इसका परीक्षण नहीं किया है), लेकिन यह एक रेगेक्स के साथ कैप्चर करने के लिए बहुत कठिन होगा। इसका मतलब यह भी है कि "पहिया को फिर से मजबूत करना" नहीं है जबकि मैं काम करने की कोशिश कर रहा हूं।
ब्लडगैन

2
बाहरी उपकरणों के माध्यम से पाठ को खिलाने की क्षमता है, इसलिए मैं आमतौर पर विंडोज पर विम और साइगविन की सिफारिश करता हूं । विम और शेल बस एक साथ होते हैं।
देवसोलर

2

एक विम-आधारित उत्तर:

:%s/\(^.*\n\)\1\{1,}/\1

= प्रत्येक पंक्ति को उसके बाद कम से कम एक बार , उसी पंक्ति से बदलें ।


2

एक और, विम 7.4.218 या बाद में ग्रहण करते हुए:

function! s:Uniq(line1, line2)
    let cursor = getcurpos()
    let lines = uniq(getline(a:line1, a:line2))
    if setline(a:line1, lines) == 0 && len(lines) <= a:line2 - a:line1
        silent execute (a:line1 + len(lines)) . ',' . a:line2 . 'd _'
    endif
    call setpos('.', cursor)
endfunction

command! -range=% Uniq call <SID>Uniq(<line1>, <line2>)

यह आवश्यक रूप से अन्य समाधानों से बेहतर नहीं है, हालांकि।


2

यहाँ प्रीबिन गुलबर्ग और पीट डेलपोर्ट द्वारा एक पुराने (2003) विम (गोल्फ) पर आधारित एक समाधान है ।

  • यह जड़ है %g/^\v(.*)\n\1$/d
  • अन्य समाधानों के विपरीत, यह एक फ़ंक्शन में इनकैप्सुलेट किया गया है, इसलिए यह खोज रजिस्टर को संशोधित नहीं करता है, न ही अनाम रजिस्टर।
  • और इसके उपयोग को सरल बनाने के लिए इसे एक कमांड में रखा गया है:
    • :Uniq(समतुल्य :%Uniq),
    • :1,Uniq (बफर की शुरुआत से वर्तमान लाइन तक),
    • नेत्रहीन चयन लाइनों + हिट :Uniq<cr>(में विम द्वारा विस्तारित :'<,'>Uniq)
    • आदि ( :h range)

यहाँ कोड है:

command! -range=% -nargs=0 Uniq <line1>,<line2>call s:EmuleUniq()

function! s:EmuleUniq() range
  let l1 = a:firstline
  let l2 = a:lastline
  if l1 < l2
    " Note the "-" to avoid spilling over the end of the range
    " Note also the use of ":delete", along with the black hole register "_"
    silent exe l1.','l2.'-g/^\(.*\)\n\1$/d _'

    call histdel('search', -1)          " necessary
    " let @/ = histget('search', -1)    " useless within a function
  endif
endfunction

नोट: उनके पहले प्रयास थे:

" Version1 from: Preben 'Peppe' Guldberg <peppe {at} xs4all {dot} nl>
" silent exe l1 . ',' . (l2 - 1) . 's/^\(.*\)\%(\n\%<' . (l2 + 1)
      " \ . 'l\1$\)\+/\1/e'

" Version from: Piet Delport <pjd {at} 303.za {dot} net>
" silent exe l1.','l2.'g/^\%<'.l2.'l\(.*\)\n\1$/d'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.