2010-01-21 16 views
32

मैं विम के विकल्प के आदेश के बारे में पता चला ...मैं विम में निर्देशिका में रिकर्सिव रूप से कैसे खोज और प्रतिस्थापित कर सकता हूं?

:%s/replaceme/replacement/gi 

और vimgrep ...

:vimgrep /findme/gj project/**/*.rb 

उनके आदेश में एक के तहत सभी फ़ाइलों में एक स्थानापन्न करने के लिए गठबंधन करने के लिए एक रास्ता है निर्देशिका?

+0

[यहां] (http: // stackoverflow।com/a/13944042/834176) पुनरावर्ती रूप से खोजने और प्रतिस्थापित करने का एक तरीका है, लेकिन केवल संस्करण नियंत्रण के तहत फ़ाइलों पर (यदि आप वास्तव में निर्देशिका के अंतर्गत * सभी * फ़ाइलों को खोजना चाहते हैं तो इसे सामान्यीकृत किया जा सकता है)। –

उत्तर

47

भले ही मैं एक वीम उपयोगकर्ता हूं, मैं आम तौर पर इस प्रकार की चीज़ के लिए find और sed का उपयोग करता हूं। sed के लिए रेगेक्स सिंटैक्स विम के समान है (वे दोनों ed के वंशज हैं), हालांकि समान नहीं हैं। जीएनयू sed के साथ आप इन-प्लेस संपादन के लिए -i का भी उपयोग कर सकते हैं (आमतौर पर sed संशोधित संस्करण को stdout में उत्सर्जित करता है)।

उदाहरण के लिए:

find proj -name '*.rb' -type f -exec sed -i -e 's/regex/replacement/g' -- {} + 

टुकड़ा टुकड़ा द्वारा:

  • "proj" पेड़ में proj = खोज
  • -name '*.rb' = के लिए चीजों को जिनके नाम मैच '* .rb'
  • -type f = और नियमित फाइलें हैं (निर्देशिकाएं, पाइप, सिम्लिंक आदि नहीं।)
  • -exec sed = इन तर्कों के साथ sed चलाएँ:
    • -i = यथा-स्थान संपादित करता है के साथ
    • -e 's/regex/replacement/g' = एक "विकल्प" कमांड (निष्पादित जो विम के :s के लगभग समान, लेकिन ध्यान दें % की कमी - यह sed में डिफ़ॉल्ट)
    • -- = झंडे के अंत में, फ़ाइल नाम यहाँ शुरू
    • {} है = इस बताता find th कि ई फ़ाइल नाम यह पाया यह एक बार चलाने की तुलना में आम तौर पर और अधिक कुशल संभव के रूप में कुछ sed आमंत्रण (में तर्क समूह के लिए sed के कमांड लाइन यहाँ
    • + पर रखा जाना चाहिए = इस बताता find कि -exec कार्रवाई समाप्त हो गया है, और हम चाहते हैं प्रति फ़ाइल नाम)। प्रति फ़ाइल नाम पर इसे चलाने के लिए आप + के बजाय \; का उपयोग कर सकते हैं।

यह जीएनयू sed और find साथ सामान्य समाधान है। इसे विशेष मामलों में थोड़ा सा छोटा किया जा सकता है। उदाहरण के लिए, यदि आप जानते हैं कि आपका नाम पैटर्न किसी भी निर्देशिका से मेल नहीं खाएगा, तो आप -type f छोड़ सकते हैं। यदि आप जानते हैं कि आपकी कोई भी फाइल - से शुरू नहीं होती है तो आप -- छोड़ सकते हैं। Here's an answer I posted to another question with more details on passing filenames found with find to other commands.

+6

इसे 'sed' करने से पहले सुनिश्चित करें और अपने 'ढूंढ' का परीक्षण करें - यह अत्यधिक समावेशी होने पर वास्तव में खराब हो सकता है। 'Sed' '-c' (' --copy') विकल्प देने के लिए भी एक अच्छा विचार है, जो इसे केवल-पढ़ने वाली फ़ाइलों के साथ गड़बड़ कर रखेगा। – Cascabel

+0

@ ब्रोस्लो मेला पर्याप्त है। मैंने जवाब को सुरक्षित/अधिक सामान्य होने के लिए अद्यतन किया है। (उस ने कहा, लिनक्स पर कम से कम ARG_MAX बहुत बड़ा है, और प्रश्न में वर्णित उपयोग के मामले में, रिक्त स्थान या विशेष वर्णों के साथ फ़ाइल नाम बहुत अजीब होंगे।) –

+0

यदि आप इस विधि का उपयोग करते हैं तो आप संरचना का उपयोग नहीं कर सकते क्योंकि sed इसका समर्थन नहीं करता है, आप 'vim -c'%/regex/replacement/gc '-c' wq '- {} \; का उपयोग कर सकते हैं, इस तरह आप अपने परिवर्तनों की पुष्टि भी कर सकते हैं – Funonly

4

एक प्लगइन है जो ऐसा करने का प्रयास करता है: Vimgrep Replace

ओह, प्रतीक्षा करें ... अन्य हैं: Global Replace, EasyGrep

एक नहीं प्लगइन समाधान के लिए, शायद argdo यदि आप तर्क सूची (args साथ सेट किया जा सकता है) पर vimgrep के उत्पादन मिल सकता है में मदद मिलेगी, लेकिन मैं विवरण पता लगाने के लिए नहीं कर पा रहे। मुझे खुशी होगी अगर किसी ने विचार लिया और उस पर सुधार किया ... तो यहां यह है।

पहली प्लगइन के पीछे मूल विचार (मुझे लगता है कि अन्य भी ...) vimgrep पहले उपयोग करना है, फिर :cnext के साथ मैचों के माध्यम से चक्र और प्रत्येक पंक्ति पर प्रतिस्थापन आदेश लागू करें। इसे पूरा करने के लिए एक समारोह इसे vvrrc में रखने के लिए काफी छोटा हो सकता है। (हो सकता है कि आप प्लगइन के स्रोतों में से एक उठा सकते हैं?)

(मुझे लगता है कि एचजीमेनेज एक समाधान पर हो सकता है, लेकिन यह उचित है या नहीं, यह संभवतः संसाधित होने वाली फ़ाइलों की संख्या पर निर्भर करेगा ... प्लगइन्स ध्यान दिए बिना ठीक होना चाहिए।)

+0

धन्यवाद, लेकिन arrrrgh! क्या कोई अन्य #! * और% प्लगइन इंस्टॉल किए बिना ऐसा करने का कोई तरीका है? – Ethan

+0

@ ईथन: मैं आपके लिए महसूस करता हूं। :-) मुझे लगता है कि इसमें एक तरीका होना चाहिए: तर्क,: argdo,: copen या जो कुछ भी ... मैं बस vimgrep का उपयोग नहीं करता है इसके बारे में पहले सोचा था और एक साथ रखने में सक्षम नहीं लग रहा है अभी तक आपके लिए सही फिक्स। लेकिन मैं अभी भी कोशिश कर रहा हूं, तो शायद मैं कुछ और साथ आऊंगा। –

+0

ओह ठीक है ... मुझे वास्तव में एक साफ और सरल नो-प्लगइन समाधान नहीं मिल रहा है या निश्चित रूप से मुझे आश्वासन देता हूं कि कोई भी नहीं है। मेरा विम-फू मुझे असफल कर रहा है! :-(प्लगइन्स अच्छा लगते हैं, हालांकि, शायद वे एक कोशिश के लायक होंगे ... –

4

एक तरीका उन सभी फ़ाइलों को खोलना होगा जिन्हें आप प्रतिस्थापन (या किसी भी कमांड) पर चलाने के लिए चाहते हैं, और :bufdo <cmd> चलाएं, जो सभी खुले बफर पर <cmd> चलाएंगे।

7

आप vimgrep तो एक मैक्रो है कि इस तरह vimgrep उत्पादन में प्रत्येक पंक्ति के लिए चला जाता है और की जगह है, कुछ रिकॉर्ड पड़ सकते है: (! # टिप्पणी में टाइप न)

:set autowrite     #automatically save the file when we change buffers 
:vimgrep /pattern/ ./**/files 
qa        #start recording macro in register a 
:s/pattern/replace/g   #replace on the current line 
:cnext       #go to next matching line 
q        #stop recording 
[email protected]       #repeat the macro 10000 times, or until stopped by 
           #an "error" such as reaching the end of the list 
:set noautowrite 

मैं परीक्षण नहीं किया यह, इसलिए इसे थोड़ा tweaking की आवश्यकता हो सकती है - कुछ फ़ाइलों पर इसका परीक्षण करें जिन्हें आप पहले गड़बड़ नहीं कर रहे हैं।

इस ओवर सेड का लाभ यह है कि विम रेगेक्स अधिक शक्तिशाली हैं, और आप प्रत्येक विकल्प को सत्यापित करने के लिए सी विकल्प जोड़ सकते हैं।

संपादित करें: मैंने अपनी मूल पोस्ट को गलत होने के बाद संशोधित किया। मैं प्रत्येक फ़ाइल में पहला मैच खोजने के लिए 1vimgrep का उपयोग कर रहा था, लेकिन मैंने दस्तावेज़ों को गलत तरीके से पढ़ा - यह केवल सभी फ़ाइलों में एक मैच पाता है।

+0

कूल! एक अभिव्यक्ति समाधान की तलाश में मैंने कभी मैक्रो पर विचार करना बंद नहीं किया ... मुझे अब मूर्खतापूर्ण लगता है। +1। :-) –

+0

आपने अभी मुझे काम के घंटे बचाए हैं, धन्यवाद !!! : डी को फ़ाइल के किसी अन्य हिस्से में किसी XML फ़ाइल में किसी मान को कॉपी करने की आवश्यकता है, फिर 200 + फाइलों में इसे कम करें। – Jason

45

args और argdo आपको जो चाहिए वह करना चाहिए, उदा।

:args spec/javascripts/**/*.* 
:argdo %s/foo/bar/g 

this page देखें।

+0

धन्यवाद! यह बहुत अच्छा है :) – starikovs

+1

व्हाउ विमस्किल ++ –

+1

पीड़ा और पूछताछ करियर की पसंद के वर्षों आज समाप्त –

0

यह छोटी संख्या में फ़ाइलों के लिए काम करता है।

vim `find। -टाइप एफ `

: bufdo% s/pattern/replacement/gec | अद्यतन

संबंधित मुद्दे

 संबंधित मुद्दे