सभी प्रोजेक्ट फ़ाइलों में विम को खोजें और बदलें


117

मैं विम में सभी प्रोजेक्ट फ़ाइलों में खोज-और-प्रतिस्थापन (पुष्टि के साथ) करने का सबसे अच्छा तरीका ढूंढ रहा हूं। "प्रोजेक्ट फाइल्स" से मेरा मतलब है कि वर्तमान डायरेक्टरी में फाइलें, जिनमें से कुछ को ओपन नहीं करना है।

ऐसा करने का एक तरीका वर्तमान निर्देशिका में सभी फ़ाइलों को खोलना हो सकता है:

:args ./**

और फिर सभी खुली फ़ाइलों पर खोज और प्रतिस्थापित करें:

:argdo %s/Search/Replace/gce

हालांकि, जब मैं ऐसा करता हूं, तो विम का मेमोरी उपयोग कुछ दर्जन एमबी से लेकर 2 जीबी तक बढ़ जाता है, जो मेरे लिए काम नहीं करता है।

मेरे पास भी EasyGrep प्लगइन स्थापित है, लेकिन यह लगभग कभी भी काम नहीं करता है - या तो यह सभी घटनाओं को नहीं ढूंढता है , या जब तक मैं दबाता हूं तब तक यह लटका रहता है CtrlC। अब तक इस कार्य को पूरा करने के लिए मेरा पसंदीदा तरीका यह है कि ack-grep कि खोज शब्द के लिए , यह उपयोग करते हुए क्विकफिक्स विंडो किसी भी फ़ाइल को खोलें जिसमें शब्द शामिल है और जो पहले नहीं खोला गया था, और अंत में :bufdo %s/Search/Replace/gce

मैं या तो एक अच्छे, काम करने वाले प्लगइन की तलाश कर रहा हूं, जिसका उपयोग इसके लिए किया जा सकता है, या वैकल्पिक रूप से एक कमांड / सीक्वेंस जो कि मैं अब उपयोग कर रहा हूं, से आसान होगा।


1
@ कैस्केबेल जब से आपने यह टिप्पणी लिखी है, एक vi.stackexchange.com साइट है।
फ़्लिकम

जवाबों:


27

ग्रील मेरे लिए अच्छा काम करता है।

जीथब पर एक रोगज़नक़ तैयार संस्करण भी है ।


8
यह स्थापित किया है, मैं देख रहा हूँ अन्य आदेशों की तरह :Gsearchऔर :Gbuffersearchमौजूद हैं, लेकिन जब मैं टाइप :Greplaceमैं Not an editor command: Greplace
रेमन तयाग

डॉक्स के अनुसार, वाक्य रचना है: :Gsearch [<grep-option(s)>] [[<pattern>] [<filename(s)>]] इसलिए आप उदाहरण के लिए, एक पुनरावर्ती खोज का उपयोग कर सकते हैं::Gsearch -r pattern dir/
vitorbal

मुझे Greplace के बारे में नफरत है कि यदि पैटर्न फ़ाइल नाम में है, तो Greplace विफल हो जाता है, क्योंकि आप अंत में इसे फ़ाइल नाम में बदलना चाहते हैं।
डैनियल

2
6 साल बाद यहां कुछ भी असामान्य नहीं है, लेकिन 3+ साल पहले अंतिम अपडेट के लिए कुछ नए उत्तरों ( github.com/yegappan/greplace ) की तुलना में यह प्लगइन गंभीर रूप से पुराना है । मैं सिड द्वारा निर्मित समाधान को देख सकता हूं: stackoverflow.com/a/38004355/2224331 (यह मेरे लिए किसी अन्य खाते पर नहीं है, सिर्फ एक संयोग है: P)
SidOfc

99

यहाँ अन्य बड़ा विकल्प केवल विम का उपयोग नहीं करना है:

sed -i 's/pattern/replacement/' <files>

या यदि आपके पास फ़ाइलों की सूची बनाने का कोई तरीका है, तो शायद कुछ इस तरह है:

find . -name *.cpp | xargs sed -i 's/pattern/replacement/'
grep -rl 'pattern1' | xargs sed -i 's/pattern2/replacement/'

और इसी तरह!


धन्यवाद! मुझे वास्तव में इस पुराने स्कूल कमांड लाइन सामान को सीखने की आवश्यकता है। मुझे लगता है कि यह सबसे अच्छा जवाब है। क्या ये रेगीक्स पेरल रेग्जेस या विम रेगेक्स या कुछ अन्य तरह के रीजेक्स हैं?
एरिक जॉनसन

2
@EricJohnson: वे ... sedregexes, जो मूल रूप से POSIX.2 बुनियादी नियमित अभिव्यक्ति हैं, लेकिन वास्तव में नहीं (यह मैनपेज में है) - वे \nमैच के नए बिंदुओं, और कुछ अन्य समान चीजों को छोड़ देते हैं। इसलिए वे grepनियमित रूप से बहुत अधिक समान हैं ।
कास्केलबेल

क्या आपके पास-कमांड कमांड में -i का कोई कारण है? मैन पेज कहता है कि एक्सटेंशन को निर्दिष्ट करने के लिए है, लेकिन आप वास्तव में एक निर्दिष्ट करने के लिए प्रकट नहीं होते हैं।
डेवकरो

ठीक है, यह वास्तव में ऐसा लगता है कि 'एस / पैटर्न / प्रतिस्थापन /' विस्तार है, मुझे लगता है कि मैं अब समझता हूं।
डेवकरो

11
मैक ओएस एक्स पर मेरे लिए काम करने वाली एकमात्र sed कमांड थी:find . -type f | LANG=C xargs sed -i '' 's/SEARCH/REPLACE/g'
ghodss

74

संपादित करें: उपयोग करें cfdocdo इसे पूरा करने के लिए चलाए जाने वाले आदेशों की मात्रा को कम करने के बजाय कमांड का करें (क्योंकि प्रत्येक फ़ाइल पर कमांड चलाते cdoसमय प्रत्येक तत्व cfdoपर कमांड चलाता है)

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

1. :grep <search term>
2. :cdo %s/<search term>/<replace term>/gc
3. (If you want to save the changes in all files) :cdo update

( cdoदी गई कमांड को क्विकफिक्स लिस्ट में प्रत्येक पद पर निष्पादित करता है, जिसे आपकी grepकमांड पॉप्युलेट करती है।)

( cयदि आप हर बार पुष्टि किए बिना प्रत्येक खोज शब्द को बदलना चाहते हैं, तो 2 डी कमांड के अंत में निकालें )


12
इसके अलावा आप :cdo updateसभी फ़ाइलों में परिवर्तन को बचाने के लिए जोड़ सकते हैं ।
झाई ली

1
लेकिन यह वर्तमान बफर संशोधित होने पर अगले बफर पर स्विच करने से पहले हर बार नहीं सहेजने की चेतावनी देने के लिए रुक जाएगा।
lfree

1
@ धन्यवाद, मैंने जवाब में जोड़ दिया है; @ शेल्फ मैं व्यक्तिगत रूप से प्रत्येक परिवर्तन की पुष्टि करना पसंद करता हूं, लेकिन आप cदूसरी कमांड के अंत में इसे हटा सकते हैं (बस उपयोग g) इसे खोज के लिए और पुष्टि के लिए पूछे बिना बदल सकते हैं
सिड

1
: cdo% s / खोज शब्द / बदलें शब्द / g केवल पहली घटना को प्रतिस्थापित करता है, लेकिन मेरी vim में दूसरी घटना के लिए काम नहीं करता है
sunxd

3
उपयोग के लिए update, मुझे करना था:cdo %s/<search term>/<replace term>/g | update
gabe

34

मैंने इस समस्या को हल करने के लिए ack और Perl का उपयोग करने का निर्णय लिया है ताकि GNU सबसेट के बजाय अधिक शक्तिशाली पूर्ण Perl नियमित अभिव्यक्तियों का लाभ उठाया जा सके।

ack -l 'pattern' | xargs perl -pi -E 's/pattern/replacement/g'

व्याख्या

एसीके

एसीके एक भयानक कमांड लाइन टूल का एक मिश्रण है कि है grep, findहै, और पूर्ण पर्ल नियमित अभिव्यक्ति (न केवल जीएनयू सबसेट)। शुद्ध पर्ल में लिखा गया है, इसका तेज़, इसमें सिंटैक्स हाइलाइटिंग है, पारंपरिक अनुभाग उपकरण की तुलना में प्रोग्रामर के लिए विंडोज और इसके फ्रेंडलीयर पर काम करता है। इसके साथ उबंटू पर स्थापित करें sudo apt-get install ack-grep

xargs

Xargs एक पुराना यूनिक्स कमांड लाइन टूल है। यह मानक इनपुट से आइटम पढ़ता है और मानक इनपुट के लिए पढ़ी गई वस्तुओं द्वारा निर्दिष्ट कमांड निष्पादित करता है। इसलिए मूल रूप से ack द्वारा निर्मित फाइलों की सूची perl -pi -E 's/pattern/replacemnt/g'कमांड के अंत में संलग्न की जा रही है ।

perl -pi

पर्ल एक प्रोग्रामिंग लैंग्वेज है। -P विकल्प आपके प्रोग्राम के चारों ओर एक लूप बनाने का कारण बनता है जो फ़ाइल नाम तर्कों पर आधारित होता है। फ़ाइल के स्थान पर -i विकल्प पर्ल को संपादित करता है। आप बैकअप बनाने के लिए इसे संशोधित कर सकते हैं। -E विकल्प पर्ल को प्रोग्राम के रूप में निर्दिष्ट कोड की एक पंक्ति को निष्पादित करने का कारण बनता है। हमारे मामले में कार्यक्रम सिर्फ एक पर्ल रेगेक्स प्रतिस्थापन है। पर्ल कमांड लाइन विकल्पों के बारे में अधिक जानकारी के लिए perldoc perlrun। पर्ल के बारे में अधिक जानकारी के लिए http://www.perl.org/ देखें ।


मुझे यह उत्तर पसंद है क्योंकि यह साइबरविन की लाइन एंडिंग के साथ भी काम करता है। ध्यान दें कि यह संशोधित लाइनों के अंत में एक \ r जोड़ देता है, लेकिन sed का उपयोग करते समय, यह हर नई पंक्ति को बदल देगा , जिससे आपका विचलन अनुपयोगी हो जाएगा। पर्ल थोड़ा और अधिक समझदार है, और यह खोज और प्रतिस्थापन के लिए एक बहुत अच्छा एक-लाइनर है। धन्यवाद!
एंड्रयू

@ और, मुझे यकीन नहीं है कि आपके मामले में गलत हो रहा है। क्या यह आपके regexps में \ n के बजाय \ R का उपयोग करने में आपकी मदद करेगा? Perldoc.perl.org/perlrebackslash.html#Misc में \ R अनुभाग देखें । इसके अलावा perldoc.perl.org/perlre.html#Regular-Expressions आज़माएं । पर्ल बेहद क्रॉस प्लेटफॉर्म है और मुझे यकीन है कि आपके लिए मैंगल्ड लाइन एंडिंग का अंत नहीं है।
एरिक जॉनसन

मेरे regex में कोई भी नया अंक नहीं है, इन कार्यक्रमों के साइबर संस्करण स्वचालित रूप से संशोधित प्रत्येक पंक्ति के अंत में \ r जोड़ते हैं। मैं विशेष रूप से पर्ल संस्करण को पसंद करता था क्योंकि यह केवल उन रेखाओं को संशोधित करता है जो मैच करती हैं जबकि sed सभी लाइनों को संशोधित करेगा , भले ही वे regex से मेल न खाते हों।
एंड्रयू

क्या होगा अगर फ़ाइल के पथ में रिक्त स्थान हैं?
shengy

23

शायद ऐसा करें:

:noautocmd vim /Search/ **/*
:set hidden
:cfirst
qa
:%s//Replace/gce
:cnf
q
1000@a
:wa

स्पष्टीकरण:

  • :noautocmd vim /Search/ **/*⇒ गति के लिए ऑटोकैड्स ( ) को ट्रिगर किए बिना cwd की सभी उपनिर्देशिकाओं की सभी फाइलों में लुकअप ( vimसंक्षिप्त नाम है vimgrep) पैटर्न :noautocmd
  • :set hidden ⇒ एक खिड़की में प्रदर्शित नहीं होने वाले संशोधित बफ़र्स की अनुमति दें (आपके vimrc में हो सकता है)
  • :cfirst ⇒ पहले खोज परिणाम पर जाएं
  • qa रजिस्टर में किसी मैक्रो रिकॉर्डिंग शुरू ⇒ एक
  • :%s//Replace/gce⇒ अंतिम खोज पैटर्न की सभी घटनाओं को बदलें (अभी भी /Search/उस समय)Replace :
    • एक ही लाइन पर कई बार (g ध्वज)
    • उपयोगकर्ता की पुष्टि ( cध्वज) के साथ
    • त्रुटि के बिना अगर कोई पैटर्न नहीं मिला ( eध्वज)
  • :cnfvimकमांड द्वारा बनाई गई सूची में अगली फ़ाइल पर जाएं
  • q ⇒ मैक्रो रिकॉर्ड करना बंद कर दें
  • 1000@a ⇒ 1000 बार रजिस्टर में संग्रहित मैक्रो चलाएं
  • :wa ⇒ सभी संशोधित बफ़र्स को बचाएं

* संपादित करें * विम 8 रास्ता:

विम 8 के साथ शुरू करने का एक बेहतर तरीका है, क्योंकि यह :cfdoउपसर्ग सूची में सभी फाइलों पर पुनरावृत्त करता है:

:noautocmd vim /Search/ **/*
:set hidden
:cfdo %s//Replace/gce
:wa

आप चाहते हैं कि हमारे लिए मृत्यु दर थोड़ी कम हो। अगर आपको हर बार यह "अनुक्रम" करने की आवश्यकता है, तो यह मेरे लिए स्पष्ट नहीं है। मैं तेजी से कर रहा हूँ कि मेरी जंग लगी पुरानी डेल्फी 5 का उपयोग करके निश्चित रूप से मुझे कुछ याद आ रहा है।
लेवेन कीर्सेमेकर्स

1
@ लाइव: आप सही हैं, यह बिना टिप्पणियों के थोड़ा अस्पष्ट है। मैं कुछ स्पष्टीकरण विकसित करूंगा।
बेनोइट

+1 लेकिन हालांकि vimमुझे कई चीजों के लिए जीत मिली है, लेकिन मुझे लगता है कि मैं इसके साथ पावरग्रेप में रहूंगा।
लेवेन केर्सेमेकर्स

आपके उत्तर के लिए और सभी आदेशों की व्याख्या के लिए धन्यवाद, मैं वास्तव में इसकी सराहना करता हूं। मैं दूसरे उत्तर को स्वीकार कर रहा हूं क्योंकि मैं इसके लिए एक प्लगइन का उपयोग करना पसंद करता हूं।
Psyho

मैंने इसे नीचे चिह्नित किया है क्योंकि यह अधिक भ्रम का कारण बनता है, इस सवाल को समझने वाले किसी के स्तर और इस उत्तर को समझने के लिए आवश्यक स्तर के बीच असमानता को देखते हुए।
लॉयड मूर

22

:argsशेल कमांड से पॉपुलेट करें

शेल कमांड के माध्यम से फ़ाइलों की आपूर्ति करना संभव है (कुछ ऑपरेटिंग सिस्टम पर 1 ) :args

उदाहरण के लिए, यदि आपके पास ack 2 स्थापित है,

:args `ack -l pattern`

ack को 'पैटर्न' वाली फ़ाइलों की सूची वापस करने के लिए कहेंगे और इन्हें तर्क सूची में डाल देंगे।

या सादे ओल 'grep के साथ मुझे लगता है कि यह होगा:

:args `grep -lr pattern .`  


फिर आप :argdoओपी द्वारा वर्णित अनुसार उपयोग कर सकते हैं :

:argdo %s/pattern/replacement/gce


आबाद :argsQuickFix सूची से

इसके अलावा एक साधारण उपयोगकर्ता परिभाषित कमांड का वर्णन करने वाले संबंधित प्रश्न के लिए नेलस्ट्रॉम के उत्तर की जांच करें जो वर्तमान उपसर्ग सूची से arglist को पॉप्युलेट करता है। यह कई कमांड और प्लगइन्स के साथ बढ़िया काम करता है जिसका आउटपुट क्विकफिक्स लिस्ट ( :vimgrep, :Ack3 , :Ggrep4 ) में समाप्त होता है ।

प्रोजेक्ट विस्तृत खोज करने का क्रम तब किया जा सकता था:

:vimgrep /pattern/ **/*
:Qargs 
:argdo %s/findme/replacement/gc

जहां :Qargsउपयोक्ता परिभाषित कमांड के लिए कॉल है जो क्विकफिक्स लिस्ट से आर्ग्लिस्ट को पॉप्युलेट करता है।

आपको लिंक भी मिलेंगे आगामी चर्चा सरल प्लगइन्स मिलेंगे जो इस वर्कफ़्लो को 2 या 3 कमांड तक ले जाते हैं।

लिंक

  1. : h {arglist} arglist} - vimdoc.sourceforge.net/htmldoc/editing.html####livegg}
  2. ack - betterthangrep.com/
  3. ack.vim - github.com/mileszs/ack.vim
  4. भगोड़ा - github.com/tpope/vim-fugitive

1
पहली फ़ाइल के बाद argdo बंद हो जाता है एक लिखने की समस्या के साथ
फ्रैंकनस्टर


5

यदि आप बाहरी निर्भरता शुरू करने का मन नहीं रखते हैं, तो मैंने काम करने के लिए एक प्लगइन ctrlsf.vim ( ack या ag पर निर्भर करता है ) पीसा है ।

यह ack / ag से खोज परिणाम को प्रारूपित और प्रदर्शित कर सकता है, और डिस्क पर वास्तविक फ़ाइलों में परिणाम बफर में आपके परिवर्तनों को सिंक्रनाइज़ कर सकता है।

शायद निम्नलिखित डेमो अधिक बताते हैं

ctrlsf_edit_demo


3
1. :grep <search term> (or whatever you use to populate the quickfix window)
2. :cfdo %s/<search term>/<replace term>/g | update

चरण 1 आपके इच्छित आइटम के साथ क्विकफ़िक्स सूची को पॉप्युलेट करता है। इस मामले में, यह उन खोज शब्दों के साथ प्रचारित होता है जिन्हें आप बदलना चाहते हैं grep

cfdoक्विकफ़िक्स सूची में प्रत्येक फ़ाइल पर निम्न कमांड चलाता है। :help cfdoविवरण के लिए टाइप करें।

s/<search term>/<replace term>/gप्रत्येक शब्द की जगह। /gफ़ाइल में हर घटना की जगह का मतलब है।

| update हर रिप्लेस के बाद फाइल को सेव करता है।

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


मेरे लिए NeoVim पर, ऊपर की पंक्ति 2 में किए जाने वाले एक मामूली संशोधन की आवश्यकता है: 2. :cfdo %s/<search term>/<replace term>/g | updateइसके बिना %, पैटर्न की केवल पहली घटना को प्रतिस्थापित किया जाता है।
करीम एर्गावी

धन्यवाद करीम। मैंने %sनियमित विम पर भी काम करने के बाद से उत्तर को अपडेट किया ।
काइल हिरोनिमस

0

मूल रूप से, मैं एक ही कमांड में प्रतिस्थापित करना चाहता था और महत्वपूर्ण रूप से विम के भीतर ही

@ जेफ्रोमी के उत्तर के आधार पर मैंने एक कीबोर्ड शॉर्टकट बनाया है, जिसे मैंने अपने .vimrc फ़ाइल में सेट किया था।

nmap <leader>r :!grep -r -l  * \| xargs sed -i -e 's///g'

अब vim से, नेता + r के एक स्ट्रोक पर मुझे vim में लोड की गई कमांड मिलती है, जिसे मैं नीचे की तरह संपादित करता हूं,

:!grep -r -l <find> <file pattern> | xargs sed -i -e 's/<find>/<replace>/g'

इसलिए, मैं एक ही आदेश के साथ और अधिक महत्वपूर्ण रूप से विम के भीतर ही प्रतिस्थापित करता हूं


और मैं वास्तव में grep के बजाय एजी का उपयोग करता हूं
डीपेक
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.