2013-10-25 3 views
5

मैं अपनी शेल स्क्रिप्ट में XXX नामक चर के मान के साथ फ़ॉर्म% XXX% की फ़ाइलों में टेम्पलेट स्ट्रिंग को प्रतिस्थापित करने के लिए sed का उपयोग करने का प्रयास कर रहा हूं।उस नाम के परिवर्तनीय की सामग्री के साथ फ़ाइल में स्ट्रिंग को प्रतिस्थापित करने के लिए sed का उपयोग

उदा। निम्नलिखित काम करता है पूरी तरह से

sed "s/%user_home%/$user_home/gi" 

तो अगर user_home=fred निम्नलिखित,

NameVirtualHost *:80 

<VirtualHost *:80> 
    ServerName %server_name% 

    ErrorLog /var/log/apache2/%user_home%_webapp_error.log 
    CustomLog /var/log/apache2/%user_home%_webapp.log common 

    DocumentRoot /home/%user_home%/web_app/public 
</VirtualHost> 

हो जाता है,

NameVirtualHost *:80 

<VirtualHost *:80> 
    ServerName %server_name% 

    ErrorLog /var/log/apache2/fred_webapp_error.log 
    CustomLog /var/log/apache2/fred_webapp.log common 

    DocumentRoot /home/fred/web_app/public 
</VirtualHost> 

समस्या यह है कि मैं स्पष्ट रूप से टेम्पलेट तार जानने के बिना एसईडी आदेश चलाना चाहते हैं और उनके चर आगे। यही है, यह% XXX% की तलाश करता है और उसके बाद वैरिएबल का वास्तविक नाम क्या है, इसकी देखभाल किए बिना $ XXX की सामग्री के साथ बदल देता है।

मुझे पता है कि इसे बैक-रेफरेंस के साथ कुछ करने के लिए मिला है, लेकिन मैं समझ नहीं सकता कि बैक-रेफरेंस की सामग्री का उपयोग वैरिएबल नाम के रूप में कैसे किया जाए।

मैंने कोशिश की,

sed "s/%\([a-z_]\)%/$(\1)/gi" 

लेकिन यह काम करने के लिए विफल रहा क्योंकि उसे एक चर की तलाश में $ \ 1 कहा जाता प्रतीत हो रहा है।

+1

बैकटिक वहाँ काम नहीं करेगा बिना परिवर्तित किया जा सकता है। वैरिएबल को 'sed' पर तर्क भेजकर खोल _before_ द्वारा विस्तारित किया जाता है। – Barmar

+1

पर्ल इसके लिए बेहतर होगा। यह '%' के बीच स्ट्रिंग में '$ चर' सेट करने के बाद पर्यावरण चर प्राप्त करने के लिए '$ ENV {$ variable}' का उपयोग कर सकता है। – Barmar

उत्तर

0

का उपयोग awk आप इस

awk '{gsub(/%user_home%/,"${user_home}")}1' file 
NameVirtualHost *:80 

<VirtualHost *:80> 
    ServerName %server_name% 

    ErrorLog /var/log/apache2/${user_home}_webapp_error.log 
    CustomLog /var/log/apache2/${user_home}_webapp.log common 

    DocumentRoot /home/${user_home}/web_app/public 
</VirtualHost> 

यह चर ${user_home}

3

समस्या यहां के %user_home% की जगह कर सकते हैं उस समय तक sed आदेश वास्तव में समय द्वारा चलाया जाता है (और इसलिए है यह परिवर्तनीय-नाम पुनर्प्राप्त करता है), sed कमांड पूरी तरह से इकट्ठा किया जाना चाहिए (बैश चर के मूल्य को प्रतिस्थापन स्ट्रिंग में प्रतिस्थापित करने सहित); तो सब कुछ गलत क्रम में होता है।

या, उच्च स्तरीय दृश्य लेते हुए, समस्या यह है कि sed बैश चर के बारे में नहीं जानता है, इसलिए आपको चर के विवरण प्रदान करने के लिए बैश की आवश्यकता है, लेकिन बैश को sed प्रतिस्थापन के बारे में पता नहीं है, इसलिए यह जानने का कोई तरीका नहीं है कि आपको किस चर के विवरण की आवश्यकता है।

फिक्स, जब तक आप बैश वैरिएबल का उपयोग करना चाहते हैं, तो अधिक बैश का उपयोग करना है: आपको sed पर कॉल करने से पहले प्रासंगिक चर-नामों की पहचान करने की आवश्यकता है। नीचे दिखाता है कि आप यह कैसे कर सकते हैं। ।

grep -o '%[a-z_][a-z_]*%' FILE | grep -o '[a-z_][a-z_]*' | sort -u 

(पहले grep रूप %...% के सभी भाव हो जाता है दूसरा grep फिल्टर:


, तो आप इस तरह कुछ लिख सकते हैं आपकी फ़ाइल के सभी चर-नामों की सूची प्राप्त करने के लिए प्रतिशत-संकेतों के बाहर; या यदि आप चाहें तो sed का उपयोग कर सकते हैं। sort -u डुप्लीकेट को समाप्त करता है, क्योंकि आपको केवल विशिष्ट चर-नामों की सूची की आवश्यकता है।)

उस के साथ सशस्त्र, आप एक sed आदेश है कि सभी आवश्यक प्रतिस्थापन प्रदर्शन को इकट्ठा कर सकते हैं:

sed_args=() 
while read varname ; do 
    sed_args+=(-e "s/%$varname%/${!varname}/g") 
done < <(grep -o '%[a-z_][a-z_]*%' FILE | grep -o '[a-z_][a-z_]*' | sort -u) 
sed "${sed_args[@]}" FILE 

(नोट ${!varname} के उपयोग "मतलब करने के लिए एक चर-नाम के रूप में $varname का मूल्य लेते हैं, और कि चर के मूल्य वापसी अप्रत्यक्ष विस्तार "" यह वही है §3.5.3 "Shell Parameter Expansion" of the Bash Reference Manual कहता है ")

आप एक समारोह में इस लपेट कर सकते हैं:।।

function replace_bash_variables() { 
    local file="$1" 
    local sed_args=() 
    local varname 
    while read varname ; do 
     sed_args+=(-e "s/%$varname%/${!varname}/g") 
    done < <(grep -o '%[a-z_][a-z_]*%' "$file" | grep -o '[a-z_][a-z_]*' | sort -u) 
    if [[ "${#sed_args[@]}" = 0 ]] ; then 
     # if no variables to replace, just cat the file: 
     cat -- "$file" 
    else 
     sed "${sed_args[@]}" -- "$file" 
    fi 
} 

replace_bash_variables OLD_FILE > NEW_FILE 

आप उपरोक्त को लाइन-दर-लाइन प्रोसेसिंग करने के लिए समायोजित भी कर सकते हैं, ताकि फ़ाइल को दो बार पढ़ने की आवश्यकता न हो। (यही कारण है कि आप और अधिक लचीलापन देता है, के बाद से फ़ाइल को पढ़ने दो बार मतलब है कि आप वास्तविक फ़ाइल में पारित करने के लिए है, और नहीं (माना) एक पाइप लाइन के उत्पादन के लिए लागू कर सकते हैं।)

+0

यह एक अच्छा समाधान है और समस्या हल करता है लेकिन मैं इसे काम करने के लिए नहीं मिल सकता। मैं केवल grep के आउटपुट को एक temp फ़ाइल में रीडायरेक्ट करके और फिर उस फ़ाइल को जबकि लूप में रीडायरेक्ट कर रहा हूं। उपरोक्त कोड को चलाने से मुझे -bash: अप्रत्याशित टोकन के पास वाक्यविन्यास त्रुटि '<(grep -o'% [a-z _] [a-z _] *% '"$ file" | grep -o' [a-z_ ] [ए-जेड _] * '| sort -u)'। – richard

+0

@reagleton: ओह, क्षमा करें, बेवकूफ गलती। मेरे [प्रक्रिया प्रतिस्थापन] के लिए (http://www.gnu.org/software/bash/manual/bashref.html#Process- सबस्टिट्यूशन), मैंने '<(...)' का उपयोग किया जब मुझे '<< (...) '। (मैं इस गलती को अक्सर शर्मनाक बना देता हूं। '<(...)' वास्तव में * दिखता है * जैसे यह मानक इनपुट को रीडायरेक्ट कर रहा है, लेकिन ऐसा नहीं है, यह सिर्फ फीफो या व्हाट्नॉट के नाम से बदल दिया जाता है।) – ruakh

0

उपयोग करें:

sed -E "s/%(\w+)%/\$\1/g" 

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

echo "abcdef %variable% blah" | sed -E "s/%(\w+)%/\$\1/g" 

प्रिंट:

abcdef $variable blah 
0

1 के साथ प्रयास करें sed लेकिन अभी भी पहले से की जरूरत है टी ओ पकड़ने चार के उपयोग के कारण "सेट" सामग्री चर नाम और मान की जानकारी

#!/bin/ksh 
# YourFilename contain the file name of your file to treat (here passed as 1st parameter to a script) 
YourFileName=$1 

(set | sed 's/.*/#V0r:&:r0V#/'; cat ${YourFileName}) | sed -n " 
s/$/²/ 
H 

$ { 
    x 
    s/^\(\n *\)*// 
# also reset t flag 
    t varxs 

:varxs 
    s/^#V0r:\([a-zA-Z0-9_]\{1,\}\)=\([^²]*\):r0V#²\(\n.*\)%\1%/#V0r:\1=\2:r0V#²\3\2/ 
    t varxs 
: tmpb 

# clean the line when no more occurance in text 
# s/^#V0r:\([a-zA-Z0-9_]\{1,\}\)=\([^²]*\):r0V#²\n// 
    s/^[^²]*:r0V#²\n// 

# and next 
    t varxs 


# clean the marker 
    s/²\(\n\)/\1/g 
    s/²$// 

# display the result 
    p 
    } 
" 
  • सीमा यहाँ "²" से छोड़ा नहीं गया है, इसलिए यदि ² फ़ाइल में दिखाई देते हैं, कष्टप्रद हो सकता है (ताकि यह परिवर्तन मार्कर के रूप में चार या फ़ाइल में इसका अनुवाद)
  • # V0r: और: r0V # भी मार्कर कर रहे हैं और समस्या
संबंधित मुद्दे