2010-02-22 17 views
6

मैंने अपनी कक्षाओं को वैश्विक नामस्थान से एक विशिष्ट नेमस्पेस में स्थानांतरित कर दिया है। मैंने कक्षा के नाम भी बदल दिए हैं। मैं अपनी सभी स्रोत फ़ाइलों को परिवर्तित करना चाहता हूं जो इन वर्गों का उपयोग नए प्रारूप में करते हैं। मैं या तो bash स्क्रिप्ट को सिग्विन पर sed फ़ाइल या एक पर्ल स्क्रिप्ट निष्पादित करने के बारे में सोच रहा था। मुझे bash स्क्रिप्ट के साथ परेशानी हो रही है।सी ++ वर्ग नाम बदलने के लिए स्क्रिप्ट

  1. प्रत्येक स्रोत फ़ाइल के लिए, * सीपीपी और * .hpp, रिकर्सिवली:

    यहाँ इस प्रक्रिया मैं प्रदर्शन करने के लिए कोशिश कर रहा हूँ है

  2. फ़ाइल एक पुराने वर्ग का नाम शामिल है, तो फ़ाइल को कनवर्ट करें।
  3. के लिए अंत।

Bash में मेरी समस्या यह पता लगा रही है कि फ़ाइल में पुरानी कक्षा का नाम है या नहीं। मैं हर वर्ग के नाम के लिए एक grep बयान की सोच रहा था:

for f in `find . -iname \*.[ch]pp`; 
do 
    if [ grep "Field_Blob_Medium" $f -eq 0 || grep "Field_Boolean" ]; then 
     sed -f conversion.sed $f 
    fi 
done 

एक मुद्दा है कि केवल एक आदेश Bash में हो सकता है अगर बयान, इस वाक्य रचना का उपयोग कर रहा है:

if grep "Field_Unsigned_Short" $f; 

तो मैं ऐसा नहीं कर सकते एक तार्किक या grep एस।

मैं एक नेस्टेड लूप प्रदर्शन कर सकता है, लेकिन मैं पाश के लिए एक Bash से बाहर कैसे break पता नहीं है:

OLD_CLASS_NAMES="Field_Blob_Medium Field_Boolean Field_Unsigned_Int" 
for f in `find . -iname \*.[ch]pp`; 
do 
    for c_name in $OLD_CLASS_NAMES; 
    do 
    if grep $c_name $f then 
     sed -f convert.sed $f # <-- Need to break out of inner loop after this execution. 
    fi 
    done 
done 

तो मैं कैसे हर स्रोत फ़ाइल है कि कार्रवाई करने के लिए पर सुझाव के लिए देख रहा हूँ पुराने वर्ग के नाम और उन्हें नए में परिवर्तित करें। एक सिगविन Bash स्क्रिप्ट उदाहरण को प्राथमिकता दी जाती है, हालांकि एक पर्ल स्क्रिप्ट भी स्वीकार्य होगी। इसके अलावा, स्क्रिप्ट को new फ़ाइल में रूपांतरित सामग्री को लिखने से पहले मूल स्रोत फ़ाइल की बैकअप प्रतिलिपि बनाना चाहिए।

मैं विंडोज एक्सपी और विंडोज विस्टा पर सिगविन चला रहा हूं।

+1

क्या आप सिर्फ एकाधिक regexp के साथ grep का उपयोग नहीं कर सकते? grep -e "Field_Blob_Medium" -e "Field_Boolean" -e "Field_Unsigned_Int" ... ? – lollinus

+1

प्रत्येक संसाधित फ़ाइल का बैकअप बनाने के लिए: sed -i.bak -f convert.sed $ f – lollinus

+0

'lo' 'loops से' ब्रेक 'ब्रेक हो जाता है और आप' अगर प्रोजे || प्रोग || लॉजिकल के लिए प्रोग 'या (लेकिन इस मामले में रेगेक्स विकल्प बेहतर है)। 'ढूंढ' के साथ 'के लिए' आमतौर पर एक बुरा विचार है क्योंकि फ़ाइल नामों में रिक्त स्थान होने पर यह विफल हो जाता है। 'While' में पाइप 'पाइप करना बेहतर है। –

उत्तर

2

पर्ल से संकोच न करें: यह आसान काम की इस तरह बनाता है!

#! /usr/bin/perl -i.bak 

use warnings; 
use strict; 

my $old = join "|" => qw(
    Field_Blob_Medium 
    Field_Boolean 
    Field_Unsigned_Int 
); 

chomp(@ARGV = `find . -iname \*.[ch]pp -print0 | 
       xargs -0 grep -lE '($old)'`); 

unless (@ARGV) { 
    warn "$0: nothing to do!\n"; 
    exit 0; 
} 

while (<>) { 
    s[Field_Blob_Medium] [my::ns::MediumBlob]g || 
    s[Field_Boolean]  [my::ns::Bool]g  || 
    s[Field_Unsigned_Int] [my::ns::UInt]g; 

    print; 
} 

-i स्विच इन-प्लेस संपादन के लिए है। यह स्वचालित रूप से बैकअप बनाता है और परिवर्तित परिणामों को मूल स्थानों पर लिखता है।

स्थापना @ARGV यह बनाता है जैसे कि आप केवल उन *.cpp और *.hpp फ़ाइलों है कि पुराने वर्ग के नाम हो के साथ कार्यक्रम लागू किया था। -Egrep पर स्विच नियमित विस्तारित अभिव्यक्तियों को सक्षम करता है ताकि (, ), और | मेटाएक्टएक्टर्स हैं।

अगर कोई हिट थे (अर्थात, अगर @ARGV खाली है), तब वहाँ कोई लेना देना नहीं है।

अन्यथा, प्रत्येक फ़ाइल की प्रत्येक पंक्ति के लिए पुराने नाम (मैकेनिक्स जिनमें से पर्ल आपके लिए हैंडल करता है!), Field_Blob_Medium को my::ns::MediumBlob पर नाम बदलने का प्रयास करें। ध्यान दें कि ये प्रतिस्थापन पहली सफलता के बाद समाप्त हो जाता है, इसलिए यदि किसी पंक्ति में दो अलग-अलग पुराने नाम होते हैं, तो एक प्रतिस्थापित किया जाएगा और दूसरा वही रहेगा।

आमतौर पर प्रतिस्थापन ऑपरेटर s/// लिखा जाता है, लेकिन आप उपरोक्त के रूप में ब्रैकेटिंग डिलीमीटर का उपयोग कर सकते हैं। मैंने नए नामों को बाधित करने के लिए ऐसा किया।

बेशक यह आपके वास्तविक प्रतिस्थापन के लिए एक स्टैंड-इन है।

अंत में, print संभावित रूप से संशोधित लाइन, जो -i की वजह से अद्यतन स्रोत फ़ाइल को लिखती है।

0

आप अपनी खोज में अधिक लचीलापन देने के लिए grep के लिए regex विकल्प का उपयोग कर सकते हैं। अपने उदाहरण के अनुसार:

if [ grep "Field_Blob_Medium" $f -eq 0 || grep "Field_Boolean" ]; 

हो सकता है

if [ grep -E "(Field_Blob_Medium|Field_Boolean)" ... ]; 

आप स्ट्रिंग एक साथ उन सकता है '|' अपने दिल की सामग्री के लिए।

इसके अलावा आप अपने greps

find . -name "*.hpp" or -name "*.cpp" | xargs grep -E ... 

में अपने खोजों को मर्ज कर सकते हैं ... मामले में तुम वहाँ कि पाश को आसान बनाने में करना चाहते हैं।

1

यह मेरे लिनक्स पर काम करता है।

#!/bin/bash 
OLD_NAMES="(EField_Blob_Medium|Field_Boolean|Field_Unsigned_Int)" 

find "$1" -name "*.hpp" -o -name "*.cpp" -print0 | \ 
    xargs -0 --replace grep -E "${OLD_NAMES}" {} && sed -i.save -f convert.sed {} 

क्या महत्वपूर्ण है::

  • xargs की -0 साथ लगता है की -print0 विकल्प रिक्त स्थान के साथ फ़ाइलें का प्रबंधन करता है यह दूसरों के द्वारा बताया विभिन्न चीजों का प्रबंधन करता है। यह एक विभाजक के रूप में 'शून्य' ASCII char का उपयोग करता है। Xargs का -0 विकल्प 'नल' char को विभाजक के रूप में समझता है: आप रिक्त स्थान के साथ फ़ाइल नामों का सही ढंग से प्रबंधन करते हैं।
  • --replace विकल्प
  • एसईडी पीठ ऊपर एक .save
  • एक शॉर्टकट के रूप & & काम के साथ फ़ाइल की मैं विकल्प वर्तमान संसाधित फ़ाइल से '{}' स्ट्रिंग को बदलने के लिए प्रयोग किया जाता है अगर का अभिव्यक्ति के दूसरे भाग केवल तभी कारगर साबित पहले भाग सच है

यह helsp आशा है, my2c

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