2010-04-23 8 views
6

मुझे किसी अन्य फ़ाइल की सामग्री के साथ कॉन्फ़िगरेशन फ़ाइल में टेक्स्ट के ब्लॉक को प्रतिस्थापित करने के लिए एक साधारण स्क्रिप्ट लिखनी होगी।किसी अन्य फ़ाइल की सामग्री के साथ फ़ाइल में पाठ के सीमित ब्लॉक को बदलें

server.xml

<?xml version='1.0' encoding='UTF-8'?> 
<Server port="8005" shutdown="SHUTDOWN"> 
    <Service name="Catalina"> 
    <Connector port="80" protocol="HTTP/1.1"/> 
    <Engine name="Catalina" defaultHost="localhost"> 
     <!-- BEGIN realm --> 
     <sometags/> 
     <sometags/> 
     <!-- END realm --> 
     <Host name="localhost" appBase="webapps"/> 
    </Engine> 
    </Service> 
</Server> 

realm.xml

<Realm className="org.apache.catalina.realm.UserDatabaseRealm" 
     resourceName="UserDatabase"/> 

मैं एक स्क्रिप्ट चलाने और <!-- BEGIN realm --> और <!-- END realm --> के बीच सामग्री को बदलने के realm.xml करना चाहते हैं:

के निम्नलिखित सरलीकृत फ़ाइलें के साथ मान लेते हैं लाइनों। यदि realm.xml तब बदलता है जब भी स्क्रिप्ट फिर से चलती है तो यह realm.xml की नई सामग्री के साथ फिर से लाइनों को प्रतिस्थापित कर देगी। यह कई प्रतिष्ठानों पर सेवा के स्टार्टअप पर /etc/init.d/tomcat में चलाने का इरादा है जिस पर दायरा अलग होगा।

मुझे यकीन नहीं है कि मैं इसे awk या sed के साथ कैसे कर सकता हूं।

उत्तर

12

इस आज़मा कर देखें।

python <<EOF 
    import os, sys, re 
    fname = 'server.xml' 
    os.rename(fname, fname + '.orig') 
    with open(fname + '.orig', 'r') as fin, open(fname, 'w') as fout: 
     data = fin.read() 

     data = re.sub(r'(<!-- BEGIN realm -->).*?(<!-- END realm -->)', 
      r'\1\n' + 
      'insert whatever you want here\n' + 
      r'\2\n', data, flags=re.DOTALL) 
     fout.write(data) 
    EOF 

मुझे लगता है कि एसईडी और awk अपने दिन पड़ा है: एसईडी और के लिए लंबे समय तक भी, मैं अंत में एहसास हुआ awk साथ चारों ओर खिलवाड़ करने के बाद अजगर की तरह एक आधुनिक, पठनीय, समझ में आता है, व्यापक रूप से उपलब्ध भाषा का प्रयोग कर के साथ कुछ भी गलत नहीं है।वे एक बार एक बार उपयोगी थे, लेकिन बहुत कम लोग इन दिनों दस्तावेजी सहायता के बिना या तो पढ़ या लिख ​​सकते हैं।

(स्रोत: इंटरनेट)

+0

वाह ... यह काम करता है। मैं वास्तव में समझने के लिए शाखाओं का लटका पाने की कोशिश कर रहा हूं कि क्या हो रहा है। – rmarimon

+3

"बीए" शाखाओं को "BEGIN" के लिए परीक्षण से जुड़े ब्रेसिज़ के भीतर "ए" लेबल करने के लिए और "बी" शाखाएं अंत में जब "ईएनडी" मिलती है क्योंकि यह उस परीक्षण से जुड़े ब्रेसिज़ के सेट में होती है। यह 'if/BEGIN/फिर फ़ाइल को पढ़ने जैसा है; जबकि नहीं/अंत/रेखा छोड़ें '। –

+0

मुझे इसके साथ एक वाक्यविन्यास त्रुटि मिलती है: 'sed: -e अभिव्यक्ति # 1, char 39: अप्रत्याशित '}'' –

3
TOTAL_LINES=`cat server.xml | wc -l` 
BEGIN_LINE=`grep -n -e '<!-- BEGIN realm -->' server.xml | cut -d : -f 1` 
END_LINE=`grep -n -e '<!-- END realm -->' server.xml | cut -d : -f 1` 
TAIL_LINES=$(($TOTAL_LINES-$END_LINE)) 

head -n $BEGIN_LINE server.xml > server2.xml 
cat realm.xml > server2.xml 
tail -n $TAIL_LINES server.xml > server2.xml 

(ठीक है, यह awk का उपयोग नहीं करता या sed ... मैं मान लिया है कि एक विशेष आवश्यकता :-)

+0

यह एक विशेष आवश्यकता नहीं थी ;-) – rmarimon

+0

क्या यह काम करता है? TOTAL_LINES में एक मान होगा जिसमें wc के अधिकांश संस्करणों में स्ट्रिंग "server.xml" शामिल है, इसलिए मुझे संदेह है कि अंकगणित विफल हो जाएगा। –

+0

@ विलियम पर्सेल - अच्छा बिंदु, तय। –

2

आप उपयोग कर सकते awk

awk 'FNR==NR{ _[++d]=$0;next} 
/BEGIN realm/{ 
    print 
    for(i=1;i<=d;i++){ print _[i] } 
    f=1;next 
} 
/END realm/{f=0}!f' realm.xml server.xml > temp && mv temp server.xml 

realm.xml है नहीं था पहली फ़ाइल के रूप में awk पास हो गया। एफएनआर == एनआर का मतलब है कि पहले फ़ाइल का रिकॉर्ड प्राप्त करना और परिवर्तनीय _ पर स्टोर करना है। एफएनआर! = एनआर एक बार अगली फाइल को संसाधित करेगा। अगर awk /BEGIN realm/ पाता है, तो BEGIN realm लाइन मुद्रित करें, फिर _ में संग्रहीत मुद्रित करें। ध्वज (एफ) से 1 सेट करके, BEGIN realm के बाद की शेष पंक्तियां /END realm/ तक मुद्रित नहीं की जाएंगी।

+0

यह सही दृष्टिकोण की तरह लगता है लेकिन यह बहुत ही गुप्त है। क्या आप कुछ सुराग प्रदान कर सकते हैं कि यह कैसे काम करता है? – rmarimon

+0

यह कैसे बदल सकता है ताकि यह "sed -i" जैसे प्रतिस्थापन को प्रतिस्थापित कर सके? – rmarimon

+0

आपको बस temp फ़ाइल पर रीडायरेक्ट करने की आवश्यकता है और इसे वापस नाम दें। – ghostdog74

1

इस छोटे से टुकड़ा मेरे द्वारा बनाए गए के बारे में कैसे:

sed -n \ 
    -e "1,/<\!-- BEGIN realm -->/ p" \ 
    -e"/<\!-- END realm -->/,$ p" \ 
    -e "/<\!-- BEGIN realm -->/ r realm.xml" \ 
    server.xml 

पहले आदेशों <!- BEGIN realm --> अप करने के लिए लाइनों प्रिंट दूसरा आदेश प्रिंट लाइन <!-- END realm --> पर शुरू और तीसरे आदेशों फ़ाइल 'दायरे में टेक्स्ट जोड़ें। xml '। अगर मैं केवल मार्कर लाइनों को हटाए बिना <!- BEGIN realm --> और <!-- END realm --> के बीच की रेखाओं को हटाने को सरल बना सकता हूं, तो यह जितना आसान होगा उतना आसान होगा। और यह inplace से sed के साथ किया जा सकता है !!!

sed -i -ne '/<!-- BEGIN realm -->/ {p; r realm.xml' -e ':a; n; /<!-- END realm -->/ {p; b}; ba}; p' server.xml 
+0

'' के बारे में क्या? आपका sed कमांड '' को प्रतिस्थापित नहीं करता है। – ghostdog74

+1

जब मैं इसे अपने लिनक्स मशीन में चलाता हूं तो यह करता है। इसके अलावा, यदि आप अंतिम स्क्रिप्ट के बिना कमांड चलाते हैं (-e) यह '' '' के बिना '' server.xml'' देता है। – rmarimon

+0

उबंटू सटीक पर मेरे लिए काम नहीं करता है। पाठ सम्मिलित करता है लेकिन को हटा नहीं देता है ... –

1

तुम भी एड आदेश का उपयोग कर सकते हैं (सीएफ http://wiki.bash-hackers.org/howto/edit-ed):

cat <<-'EOF' | sed -e 's/^ *//' -e 's/ *$//' | ed -s server.xml 
    H 
    /BEGIN realm/i 
    . 
    /BEGIN realm/+1,/END realm/-1d 
    .-1r realm.xml 
    wq 
EOF 
0

मैं इस एक ही जरूरत में भाग (इसलिए इस सवाल खोजने)

0

मैं आसानी से ओएस एक्स पर काम कर डेनिस समाधान प्राप्त करने में असमर्थ था (अपने बीएसडी एसईडी थोड़ा अलग है)। मुझे यह दूसरा समाधान मिला कि मैं लिनक्स और ओएस एक्स दोनों पर काम करने में सक्षम था (मेरे पास मिश्रित वातावरण है)। superuser.com पर मूल संस्करण लिनक्स पर ही काम करता है, यहाँ मैं यह तय:

lead='^<!-- BEGIN realm -->$' 
tail='^<!-- END realm -->' 
sed -e '/'"$lead"'/,/'"$tail"'/{ /'"$lead"'/{p; r realm.xml' -e' }; /'"$tail"'/p; d;} ' server.xml 
यहाँ

डेनिस कोड का एक संस्करण है कि ओएस एक्स पर भी काम करता है (कई लाइनों का प्रयोग करके):

sed -ne '/'"$lead"'/ { 
p 
r realm.xml 
:a 
n 
/'"$tail"'/ { 
    p 
    b 
} 
ba 
} 
p' server.xml 

इन दोनों कोड stdout पर आउटपुट मुद्रित करें। फ़ाइल इनलाइन को प्रतिस्थापित करने के लिए पुनर्निर्देशन का उपयोग करें, विकल्प '-i' (लिनक्स पर) या '-i ""' (बीएसडी/ओएस एक्स पर) जोड़ें।