टेक्स्ट फ़ाइल में $ {} प्लेसहोल्डर्स को कैसे बदलें?


163

मैं MySQL में एक "टेम्पलेट" फ़ाइल के आउटपुट को पाइप करना चाहता हूं, फ़ाइल जिसमें चौराहे जैसे चर हैं ${dbName}। इन उदाहरणों को बदलने और आउटपुट को मानक आउटपुट में डंप करने के लिए कमांड लाइन उपयोगिता क्या है?

जवाबों:


192

सैड !

टेम्पलेट दिया गया।

संख्या $ {i} है
शब्द $ {शब्द} है

हमें सिर्फ यह कहना है:

sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.txt

-eएक ही sedआह्वान के लिए कई तर्क पारित करने के लिए टिप के लिए जोनाथन लेफ़लर का धन्यवाद ।


13
आप उन दो sed कमांड को एक में जोड़ सकते हैं: sed -e "s / \ $ {i} / 1 /" -e "s / \ $ {word} / dog /"; यह अधिक कुशल है। आप शायद sed के कुछ संस्करणों के साथ समस्याओं में भाग सकते हैं 100 ऐसे ऑपरेशन (वर्षों पहले से समस्या - अभी भी सच नहीं हो सकता है, लेकिन एचपी-यूएक्स से सावधान रहें)।
जोनाथन लेफ़लर

1
धन्यवाद जोनाथन, वास्तव में मैं क्या देख रहा था।
दाने द साने

3
छोटे संकेत: यदि दिए गए उदाहरण में "1" या "कुत्ते" में एक डॉलर का प्रतीक होगा, तो आपको इसे बैकस्लैश के साथ बचाना होगा (अन्यथा प्रतिस्थापन नहीं होता है)।
MatthieuP

9
तुम भी जरूरत नहीं है cat। आप सभी की जरूरत है sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text
हार्डलीकॉन्मे

3
क्या होगा अगर प्रतिस्थापन पाठ एक पासवर्ड है? इस मामले में, sedबचने वाले पाठ की अपेक्षा करेंगे, जो एक परेशानी है।
जपबच्ची

177

अपडेट करें

यहाँ एक ऐसे ही सवाल पर यॉट्सएटा से एक समाधान है जो केवल $ VAR या $ {VAR} जैसे चर के लिए प्रतिस्थापन करता है, और एक संक्षिप्त एक-लाइनर है

i=32 word=foo envsubst < template.txt

बेशक अगर मैं और शब्द आपके वातावरण में हैं, तो यह सिर्फ है

envsubst < template.txt

अपने Mac पर ऐसा लगता है कि यह के भाग के रूप स्थापित किया गया था gettext और से MacGPG2

पुराना उत्तर

इसी तरह के एक सवाल पर मोगी से समाधान में सुधार किया गया है , मेरे समाधान के लिए आपको दोहरे उद्धरण चिह्नों की आवश्यकता नहीं है, मोगी का क्या है, लेकिन उनका एक लाइनर है!

eval "cat <<EOF
$(<template.txt)
EOF
" 2> /dev/null

इन दो समाधान पर शक्ति है कि आप केवल सामान्य रूप से $ ((...)) कि नहीं होती है कुछ खोल विस्तार के प्रकार, `` ... मिलता है, और $ (...), हालांकि बैकस्लैश है एक यहाँ से बच चरित्र, लेकिन आप चिंता करने की ज़रूरत नहीं है कि पार्सिंग में एक बग है, और यह कई लाइनों को ठीक करता है।


6
envsubstअगर आपके दूत निर्यात नहीं होते हैं तो मैं नंगे काम नहीं कर रहा हूँ ।
टोड्डियस ज़ो

4
@ToddiusZho: एक पर्यावरण चर के रूप में ऐसी कोई चीज नहीं है जिसे निर्यात नहीं किया जाता है - यह ठीक से निर्यात होता है जो शेल चर को पर्यावरण चर बनाता है । envsubst, जैसा कि इसके नाम से पता चलता है, केवल पर्यावरण चर को पहचानता है , शेल चर को नहीं । यह भी ध्यान देने योग्य है कि envsubstएक GNU उपयोगिता है, और इसलिए सभी प्लेटफार्मों पर पूर्वस्थापित या उपलब्ध नहीं है।
mklement0

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

1
मेरे पास एक स्ट्रिंग है जिसमें $ HOME है, मैंने पाया कि $ HOME को डिफ़ॉल्ट शेल के रूप में काम करने के लिए काम किया जाता है, इसके बजाय $ HOME को मेरे अपने / घर / zw963 के रूप में, लेकिन, ऐसा लगता है कि $ (कैट / etc / hostname) प्रतिस्थापन का समर्थन नहीं करते, इसलिए यह मेरी अपनी मांग से मेल नहीं खाता।
zw963

3
"पुराने उत्तर" के लिए धन्यवाद, क्योंकि यह न केवल चर की अनुमति देता है, बल्कि $ (ls -l) जैसे शेल कमांड भी देता है।
Alek

46

का उपयोग करें /bin/sh। एक छोटी सी शेल स्क्रिप्ट बनाएं जो चर सेट करता है, और फिर शेल का उपयोग करके टेम्पलेट को पार्स करें। ऐसा ही (नई कहानियों को सही ढंग से संभालने के लिए संपादित करें):

फ़ाइल template.txt:

the number is ${i}
the word is ${word}

फ़ाइल script.sh:

#!/bin/sh

#Set variables
i=1
word="dog"

#Read in template one line at the time, and replace variables (more
#natural (and efficient) way, thanks to Jonathan Leffler).
while read line
do
    eval echo "$line"
done < "./template.txt"

आउटपुट:

#sh script.sh
the number is 1
the word is dog

2
सिर्फ क्यों नहीं: लाइन पढ़ते समय; eval गूंज "$ लाइन"; किया <//template.txt ??? पूरे फ़ाइल को मेमोरी में पढ़ने की आवश्यकता नहीं है, केवल एक पंक्ति में एक बार सिर और पूंछ के गहन उपयोग के माध्यम से इसे बाहर थूकना है। लेकिन 'eval' ठीक है - जब तक कि टेम्प्लेट में पीछे के कोट्स जैसे शेल कैरेक्टर न हों।
जोनाथन लेफलर

16
यह बहुत खतरनाक है! bashइनपुट में सभी कमांड निष्पादित किए जाएंगे। यदि टेम्प्लेट है: "शब्द है, rm -rf $ HOME" तो आप फाइलें ढीली कर देंगे।
rzymek

1
@rzymek - याद रखें, वह इस फाइल को सीधे डेटाबेस में पाइप करना चाहता है। तो जाहिर है, इनपुट पर भरोसा है।
gnud

4
@gnud एक फ़ाइल पर भरोसा करने के बीच एक अंतर है कि यह सामग्री को संग्रहीत करने के लिए पर्याप्त है और इसमें किसी भी चीज़ को निष्पादित करने के लिए पर्याप्त भरोसा है।
मार्क

3
बाधाओं को नोट करने के लिए: (ए) इनपुट में दोहरे उद्धरण चुपचाप खारिज कर दिए जाते हैं, (बी) readकमांड, जैसा कि लिखा गया है, प्रत्येक पंक्ति से व्हाट्सएप को अग्रणी और पीछे ले जाता है और चार्ट को खाता है \ । (ग) केवल इस तरह से यदि आप पूरी तरह से छोड़ देते हैं। इनपुट पर भरोसा करें या नियंत्रित करें, क्योंकि इनपुट में एम्बेडेड कमांड प्रतिस्थापन ( `…` या $(…)) उपयोग के कारण मनमाने आदेशों के निष्पादन की अनुमति देता है eval। अंत में, एक छोटा सा मौका है जो echoअपने कमांड लाइन विकल्पों में से एक के लिए एक पंक्ति की शुरुआत में गलती करता है।
mklement0

23

मैं इस बारे में फिर से सोच रहा था, हाल ही में ब्याज दिया गया था, और मुझे लगता है कि जिस टूल के बारे में मैं मूल रूप से सोच रहा था m4, वह ऑटोलूलस के लिए मैक्रो प्रोसेसर था । इसलिए आपके द्वारा निर्दिष्ट चर के बजाय, आप उपयोग करेंगे:

$echo 'I am a DBNAME' | m4 -DDBNAME="database name"

1
इस समाधान में यहां उत्तर की कमियां हैं। क्या आप केवल DBNAME के ​​बजाय $ {DBNAME} को बदलने का कोई तरीका जानते हैं?
जैक डेविडसन

@JackDavidson मैं envsubstइस सरल चर प्रतिस्थापन / अस्थायी उपयोग के लिए उपयोग करूंगा , जैसा कि अन्य उत्तरों में वर्णित है। m4एक महान उपकरण है, लेकिन यह बहुत अधिक सुविधाओं के साथ एक पूर्ण विकसित प्रीप्रोसेसर है और इस प्रकार जटिलता की आवश्यकता नहीं है अगर आप बस कुछ चर को बदलना चाहते हैं।
इमिरिक

13

template.txt

Variable 1 value: ${var1}
Variable 2 value: ${var2}

data.sh

#!/usr/bin/env bash
declare var1="value 1"
declare var2="value 2"

parser.sh

#!/usr/bin/env bash

# args
declare file_data=$1
declare file_input=$2
declare file_output=$3

source $file_data
eval "echo \"$(< $file_input)\"" > $file_output

./parser.sh data.sh template.txt parsed_file.txt

parsed_file.txt

Variable 1 value: value 1
Variable 2 value: value 2

1
जैसा कि कहीं और नोट किया गया है: केवल इसका उपयोग करें यदि आप पूरी तरह से विश्वास करते हैं या इनपुट को नियंत्रित करते हैं, क्योंकि इनपुट में एम्बेडेड कमांड प्रतिस्थापन ( `…` या $(…)) उपयोग के कारण मनमाने आदेशों के निष्पादन की अनुमति देता है eval, और उपयोग के कारण शेल कोड का प्रत्यक्ष निष्पादन source। इसके अलावा, इनपुट में दोहरे उद्धरण चुपचाप खारिज कर दिए जाते हैं, और echoइसके कमांड लाइन विकल्पों में से एक के लिए एक पंक्ति की शुरुआत में गलती हो सकती है।
mklement0

दुर्भाग्य से, यह परिणाम फ़ाइल से सभी दोहरे उद्धरण (") को हटाता है। क्या दोहरे उद्धरण चिह्नों को हटाने के बिना भी ऐसा करने का एक तरीका है?
Ivaylo Slavov

मैंने पाया कि मैं यहाँ क्या देख रहा था: stackoverflow.com/a/11050943/795158 ; मैं envsubst का उपयोग करता था। अंतर यह है कि var का निर्यात किया जाना है जो मेरे साथ ठीक था।
Ivaylo Slavov

यदि पाठ फ़ाइल में "` "या" "है। , प्रतिस्थापन विफल हो जाएगा।
शुईकियांग

12

यहां एक मजबूत बैश फ़ंक्शन है - उपयोग करने के बावजूद eval- उपयोग करने के लिए सुरक्षित होना चाहिए।

${varName}कॉल शेल के चर के आधार पर इनपुट पाठ में सभी चर संदर्भों का विस्तार किया जाता है।

और कुछ नहीं विस्तारित किया गया है: न तो चर संदर्भ जिनके नाम (जैसे ) में संलग्न नहीं हैं , न ही कमांड प्रतिस्थापन ( और विरासत सिंटैक्स ), और न ही अंकगणितीय प्रतिस्थापन ( और विरासत सिंटैक्स )।{...}$varName$(...)`...`$((...))$[...]

$एक शाब्दिक के रूप में इसका इलाज करने के लिए \; उदाहरण के लिए:\${HOME}

ध्यान दें कि इनपुट केवल स्टड के माध्यम से स्वीकार किया जाता है ।

उदाहरण:

$ expandVarsStrict <<<'$HOME is "${HOME}"; `date` and \$(ls)' # only ${HOME} is expanded
$HOME is "/Users/jdoe"; `date` and $(ls)

समारोह स्रोत कोड:

expandVarsStrict(){
  local line lineEscaped
  while IFS= read -r line || [[ -n $line ]]; do  # the `||` clause ensures that the last line is read even if it doesn't end with \n
    # Escape ALL chars. that could trigger an expansion..
    IFS= read -r -d '' lineEscaped < <(printf %s "$line" | tr '`([$' '\1\2\3\4')
    # ... then selectively reenable ${ references
    lineEscaped=${lineEscaped//$'\4'{/\${}
    # Finally, escape embedded double quotes to preserve them.
    lineEscaped=${lineEscaped//\"/\\\"}
    eval "printf '%s\n' \"$lineEscaped\"" | tr '\1\2\3\4' '`([$'
  done
}

फ़ंक्शन मानता है कि इनपुट में कोई 0x1भी 0x2, 0x3और 0x4नियंत्रण वर्ण मौजूद नहीं हैं, क्योंकि वे वर्ण हैं। आंतरिक रूप से उपयोग किया जाता है - चूंकि फ़ंक्शन पाठ को संसाधित करता है , इसलिए यह एक सुरक्षित धारणा होनी चाहिए।


2
यह यहां सबसे अच्छे उत्तर में से एक है। उपयोग evalकरने के साथ भी यह उपयोग करने के लिए बहुत सुरक्षित है।
शुभ

1
यह समाधान JSON फ़ाइलों के साथ काम करता है! ( "ठीक से बचकर !)
WBAR

2
इस समाधान के साथ एक अच्छी बात यह है कि ${FOO:-bar}यदि आप इसे सेट करते हैं तो आपको गुम चर या केवल कुछ आउटपुट के लिए चूक प्रदान करने देंगे ${HOME+Home is ${HOME}}। मुझे थोड़ा विस्तार से संदेह है कि यह लापता चर के लिए निकास कोड भी वापस कर सकता है, ${FOO?Foo is missing}लेकिन वर्तमान में tldp.org/LDP/abs/html/parameter-substitution.html के पास इनकी सूची नहीं है अगर इसमें मदद मिलती है
स्टुअर्ट मूर

11

बनाएँ rendertemplate.sh:

#!/usr/bin/env bash

eval "echo \"$(cat $1)\""

और template.tmpl:

Hello, ${WORLD}
Goodbye, ${CHEESE}

टेम्पलेट रेंडर करें:

$ export WORLD=Foo
$ CHEESE=Bar ./rendertemplate.sh template.tmpl 
Hello, Foo
Goodbye, Bar

2
यह स्ट्रिप्स डबल उद्धृत स्ट्रिंग्स
vrtx54234

कोशिश की: eval "इको $ (बिल्ली $ 1)" - w / आउट उद्धरण, और यह मेरे लिए काम किया।
access_granted

2
सुरक्षा के दृष्टिकोण से, यह बुरी खबर है। यदि आपका टेम्पलेट शामिल है $(rm -rf ~), तो आप उसे कोड के रूप में चला रहे हैं।
चार्ल्स डफी

eval "echo \"$(cat $1)\"" बहुत अच्छा काम करता है !
देव देव ११

10

पूर्व के उत्तर के आधार पर पर्ल के साथ यहां मेरा समाधान, पर्यावरण चर की जगह:

perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1}?$ENV{$1}:"missing variable $1")/eg' < infile > outfile

2
यह भी खूब रही। हमेशा परेशान न हों, लेकिन जब आप ऐसा करते हैं, तो यह सरल और सीधे आगे होता है।
एरॉन मैकमिलिन

5

यदि आप पर्ल का उपयोग करने के लिए खुले हैं , तो यह मेरा सुझाव होगा। हालांकि शायद कुछ सेड और / या AWK विशेषज्ञ हैं जो शायद यह जानते हैं कि यह कैसे करना है। यदि आपके पास अपने प्रतिस्थापन के लिए सिर्फ dbName से अधिक के साथ एक अधिक जटिल मानचित्रण है, तो आप इसे बहुत आसानी से बढ़ा सकते हैं, लेकिन आप बस उस बिंदु पर एक मानक पर्ल स्क्रिप्ट में डाल सकते हैं।

perl -p -e 's/\$\{dbName\}/testdb/s' yourfile | mysql

एक छोटी पर्ल स्क्रिप्ट कुछ और अधिक जटिल करने के लिए (कई कुंजियों को संभालें):

#!/usr/bin/env perl
my %replace = ( 'dbName' => 'testdb', 'somethingElse' => 'fooBar' );
undef $/;
my $buf = <STDIN>;
$buf =~ s/\$\{$_\}/$replace{$_}/g for keys %replace;
print $buf;

यदि आप उपरोक्त लिपि को प्रतिस्थापित-लिपि का नाम देते हैं, तो इसे निम्नानुसार उपयोग किया जा सकता है:

replace-script < yourfile | mysql

1
एकल चर के लिए काम करता है, लेकिन मैं दूसरों के लिए 'या' कैसे शामिल करूं?
साने

2
ऐसे कई तरीके हैं जिनसे आप पर्ल के साथ ऐसा कर सकते हैं, यह सब इस बात पर निर्भर करता है कि आप इसे कितना जटिल और / या सुरक्षित बनाना चाहते हैं। अधिक जटिल उदाहरण यहां देखे
Beau Simensen

3
शेल का उपयोग करने की कोशिश की तुलना में पर्ल का उपयोग करना बहुत साफ है। अन्य उल्लिखित शेल-आधारित समाधानों में से कुछ को आज़माने के बजाय इस कार्य को करने के लिए समय व्यतीत करें।
jdigital

1
हाल ही में इसी तरह के मुद्दे से निपटना पड़ा। अंत में मैं पर्ल के साथ चला गया (envsubst थोड़ा सा आशाजनक लग रहा था, लेकिन इसे नियंत्रित करना बहुत कठिन था)।
फरवरी को

5

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

सामग्री के साथ template.txt के उदाहरण का उपयोग करना:

The number is ${i}
The word is ${word}

निम्न पंक्ति शेल को टेम्प्लेट की सामग्री को प्रक्षेपित करने का कारण बनेगी। यह मानक परिणाम को लिखने के लिए है।

i='1' word='dog' sh -c 'echo "'"$(cat template.txt)"'"'

स्पष्टीकरण:

  • iऔर wordपर्यावरण चर के रूप में पारित कर दिया जाता है जिसे क्रियान्वित करने के लिए स्कूप किया जाता है sh
  • sh पास की गई स्ट्रिंग की सामग्री को निष्पादित करता है।
  • एक दूसरे के बगल में लिखे गए तार एक स्ट्रिंग बन जाते हैं, यह स्ट्रिंग है:
    • ' echo "' + " $(cat template.txt)" + ' "'
  • चूंकि प्रतिस्थापन के बीच है ", " $(cat template.txt)" का आउटपुट बन जाता है cat template.txt
  • तो द्वारा निष्पादित आदेश sh -cबन जाता है:
    • echo "The number is ${i}\nThe word is ${word}",
    • निर्दिष्ट परिवेश चर कहाँ iऔर कहाँ wordहैं।

सुरक्षा के दृष्टिकोण से, यह बुरी खबर है। यदि आपके टेम्प्लेट में शामिल हैं, तो कहें, '$(rm -rf ~)'$(rm -rf ~)टेम्प्लेट फ़ाइल में शाब्दिक उद्धरण उसके विस्तार से पहले आपके द्वारा जोड़े गए से मेल खाएगा।
चार्ल्स डफी

मैं इन-टेंप्लेट उद्धरणों को आउट-टेम्प्लेट उद्धरणों से मेल नहीं खाता, मेरा मानना ​​है कि शेल टेम्प्लेट और इन-टर्मिनल स्ट्रिंग को स्वतंत्र रूप से हल कर रहा है (उद्धरणों को प्रभावी रूप से हटाते हुए) फिर उन्हें समेटना। परीक्षण का एक संस्करण जो आपके होम डायरेक्टरी को डिलीट नहीं करता है '$(echo a)'$(echo a)। यह पैदा करता है 'a'a। मुख्य बात यह है कि पहले का मूल्यांकन echo aकिया 'जा रहा है, जो आप के बाद से उम्मीद नहीं की जा सकती है ', लेकिन 'एक "उद्धृत स्ट्रिंग में शामिल के समान व्यवहार है ।
अप्रीरी

तो, यह इस अर्थ में सुरक्षित नहीं है कि यह टेम्पलेट लेखक को अपने कोड को निष्पादित करने की अनुमति देता है। हालाँकि उद्धरणों का मूल्यांकन कैसे किया जाता है यह वास्तव में सुरक्षा को प्रभावित नहीं करता है। किसी भी "-क्वॉट स्ट्रिंग (सहित $(...)) का विस्तार करना बिंदु है।
अप्रीरी

क्या यह बात है? मैं केवल उन्हें देख रहा हूं ${varname}, अन्य नहीं, उच्च-सुरक्षा-जोखिम विस्तार।
चार्ल्स डफी

... उस ने कहा, मुझे अलग होना चाहिए (पुन: इन-टेम्पलेट और आउट-टेम्प्लेट उद्धरण मेल करने में सक्षम हैं)। जब आप अपनी स्ट्रिंग में एक सिंगल-कोट डालते हैं, तो आप सिंगल- echo "कोटा स्ट्रिंग में विभाजित होते हैं , उसके बाद एक डबल-उद्धृत स्ट्रिंग के साथ template.txtएक और शाब्दिक स्ट्रिंग ", जिसके बाद एक एकल तर्क में बदल दिया जाता है sh -c। आप सही हैं कि 'मिलान नहीं किया जा सकता है (क्योंकि यह आंतरिक शेल के बजाय आंतरिक शेल के पास गया था), लेकिन "निश्चित रूप से हो सकता है, इसलिए एक टेम्पलेट को Gotcha"; rm -rf ~; echo "निष्पादित किया जा सकता है।
चार्ल्स डफी

4

file.tpl:

The following bash function should only replace ${var1} syntax and ignore 
other shell special chars such as `backticks` or $var2 or "double quotes". 
If I have missed anything - let me know.

script.sh:

template(){
    # usage: template file.tpl
    while read -r line ; do
            line=${line//\"/\\\"}
            line=${line//\`/\\\`}
            line=${line//\$/\\\$}
            line=${line//\\\${/\${}
            eval "echo \"$line\""; 
    done < ${1}
}

var1="*replaced*"
var2="*not replaced*"

template file.tpl > result.txt

2
यह सुरक्षित नहीं है क्योंकि यह टेम्पलेट में कमांड प्रतिस्थापन निष्पादित करेगा यदि उनके पास एक प्रमुख बैकस्लैश है जैसे\$(date)
पीटर डॉल्बर्ग

1
पीटर के वैध बिंदु के अलावा: मेरा सुझाव है कि आप कमांड के while IFS= read -r line; doरूप में उपयोग करें read, अन्यथा आप प्रत्येक इनपुट लाइन से व्हाट्सएप को अग्रणी और पीछे छोड़ देंगे। इसके अलावा, echoइसके कमांड लाइन विकल्पों में से एक के लिए एक लाइन की शुरुआत में गलती हो सकती है, इसलिए इसका उपयोग करना बेहतर है printf '%s\n'। अंत में, यह दोहरे उद्धरण के लिए सुरक्षित है ${1}
mklement0

4

मैं सिगिल जैसे कुछ का उपयोग करने का सुझाव दूंगा : https://github.com/gliderlabs/sigil

यह एकल बाइनरी के लिए संकलित है, इसलिए सिस्टम पर स्थापित करना बेहद आसान है।

तो आप निम्न की तरह एक साधारण एक लाइनर कर सकते हैं:

cat my-file.conf.template | sigil -p $(env) > my-file.conf

यह evalregex या का उपयोग करके की तुलना में बहुत सुरक्षित हैsed


2
बहुत बढ़िया जवाब! यह एक उचित टेम्प्लेटिंग सिस्टम है और अन्य उत्तरों की तुलना में बहुत आसान है।
इरफान

BTW, बजाय बचने के लिए catऔर उपयोग करने के लिए बेहतर है <my-file.conf.templateताकि आप sigilएक FIFO के बजाय एक वास्तविक फ़ाइल हैंडल दें।
चार्ल्स डफी

2

मैंने इसी बात को सोचते हुए यह धागा पाया। इसने मुझे इसके लिए प्रेरित किया (बैकटिक्स के साथ सावधान)

$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world

4
इसके लिए एक बैश शॉर्टहैंड $(cat file)है$(< file)
ग्लेन जैकमैन

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

@AththurCorenzan: वास्तव में, लाइन ब्रेक को रिक्त स्थान से बदल दिया जाता है। इसे ठीक करने के लिए, आपको उपयोग करना होगा, eval echo "\"$(cat FILE)\""लेकिन इनपुट में उस दोहरे उद्धरण में अभी भी कमी आ सकती है।
19 दिसंबर को mklement0

जैसा कि कहीं और नोट किया गया है: केवल इसका उपयोग करें यदि आप पूरी तरह से विश्वास करते हैं या इनपुट को नियंत्रित करते हैं, क्योंकि इनपुट में एम्बेडेड कमांड प्रतिस्थापन ( `…` या $(…)) उपयोग के कारण मनमाने आदेशों के निष्पादन की अनुमति देते हैं eval
mklement0

2

यहाँ बहुत सारे विकल्प हैं, लेकिन मुझे लगा कि मैं ढेर पर अपना टॉस करूँगा। यह पर्ल आधारित है, केवल फॉर्म $ {...} के चर को लक्षित करता है, फ़ाइल को एक तर्क के रूप में संसाधित करने के लिए लेता है और stdout पर परिवर्तित फ़ाइल को आउटपुट करता है:

use Env;
Env::import();

while(<>) { $_ =~ s/(\${\w+})/$1/eeg; $text .= $_; }

print "$text";

बेशक मैं वास्तव में एक प्रति व्यक्ति नहीं हूं, इसलिए आसानी से एक घातक दोष हो सकता है (हालांकि मेरे लिए काम करता है)।


1
ठीक काम करता है। आप Env::import();लाइन छोड़ सकते हैं - आयात द्वारा निहित है use। इसके अलावा, मेरा सुझाव है कि पहले मेमोरी में पूरे आउटपुट का निर्माण न करें: केवल लूप print;के $text .= $_;अंदर का उपयोग करें , और पोस्ट-लूप printकमांड को छोड़ दें ।
mklement0

1

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

$ cat config.data
    export parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA
    export parm_user=pax
    export parm_pwd=never_you_mind

$ cat go.bash
    . config.data
    echo "JDBC string is " $parm_jdbc
    echo "Username is    " $parm_user
    echo "Password is    " $parm_pwd

$ bash go.bash
    JDBC string is  jdbc:db2://box7.co.uk:5000/INSTA
    Username is     pax
    Password is     never_you_mind

यदि आपकी कॉन्फ़िग फ़ाइल शेल स्क्रिप्ट नहीं हो सकती है, तो आप इसे निष्पादित करने से पहले इसे 'संकलित' कर सकते हैं (संकलन आपके इनपुट प्रारूप पर निर्भर करता है)।

$ cat config.data
    parm_jdbc=jdbc:db2://box7.co.uk:5000/INSTA # JDBC URL
    parm_user=pax                              # user name
    parm_pwd=never_you_mind                    # password

$ cat go.bash
    cat config.data
        | sed 's/#.*$//'
        | sed 's/[ \t]*$//'
        | sed 's/^[ \t]*//'
        | grep -v '^$'
        | sed 's/^/export '
        >config.data-compiled
    . config.data-compiled
    echo "JDBC string is " $parm_jdbc
    echo "Username is    " $parm_user
    echo "Password is    " $parm_pwd

$ bash go.bash
    JDBC string is  jdbc:db2://box7.co.uk:5000/INSTA
    Username is     pax
    Password is     never_you_mind

आपके विशिष्ट मामले में, आप कुछ का उपयोग कर सकते हैं:

$ cat config.data
    export p_p1=val1
    export p_p2=val2
$ cat go.bash
    . ./config.data
    echo "select * from dbtable where p1 = '$p_p1' and p2 like '$p_p2%' order by p1"
$ bash go.bash
    select * from dbtable where p1 = 'val1' and p2 like 'val2%' order by p1

तब goSQL के उत्पादन को MySQL और वॉइला में पाइप करें, उम्मीद है कि आप अपने डेटाबेस को नष्ट नहीं करेंगे :-)।


1
आपको config.data फ़ाइल से चर निर्यात करने की आवश्यकता नहीं है; यह सिर्फ उन्हें सेट करने के लिए पर्याप्त है। आप किसी भी बिंदु पर टेम्प्लेट फ़ाइल नहीं पढ़ रहे हैं। या, शायद, टेम्पलेट फ़ाइल को संशोधित किया गया है और इसमें 'इको' ऑपरेशन शामिल हैं ... या क्या मुझे कुछ याद आ रहा है?
जोनाथन लेफ्लर

1
निर्यात पर अच्छी बात है, मैं इसे डिफ़ॉल्ट रूप से करता हूं ताकि वे उप-भागों के लिए उपलब्ध हों और जब वे बाहर निकलते हैं तो इससे कोई नुकसान नहीं होता है। 'टेम्प्लेट' फ़ाइल स्क्रिप्ट ही है जिसमें इसकी प्रतिध्वनि है। तीसरी फ़ाइल शुरू करने की आवश्यकता नहीं है - यह मूल रूप से एक mailmerge-type ऑपरेशन है।
पैक्सडिआब्लो

1
"इट्स स्क्रिप्ट विद इट इको स्टेटमेंट्स" कोई टेम्पलेट नहीं है: यह एक स्क्रिप्ट है। <Xml प्रकार = "$ TYPE"> और गूंज '<xml प्रकार = "' $ TYPE '"> के बीच पठनीयता (और स्थिरता) अंतर सोचें
पियरे-ओलिवियर वेर्स

1
@ पियरे, मेरी कॉन्फिग स्क्रिप्ट में कोई इको स्टेटमेंट नहीं हैं, वे महज एक्सपोर्ट हैं, और मैंने दिखाया है कि कैसे आप कम से कम प्री-प्रोसेसिंग से बच सकते हैं। यदि आप मेरी अन्य लिपियों (जैसे go.bash) में इको स्टेटमेंट के बारे में बात कर रहे हैं , तो आपको स्टिक का गलत अंत मिल गया है - वे समाधान का हिस्सा नहीं हैं, वे सिर्फ यह दिखाने का एक तरीका है कि चर रहे हैं सही ढंग से सेट करें।
paxdiablo

1
@paxdiablo: ऐसा लगता है कि आप बस इस सवाल को भूल गए: << मैं एक "टेम्पलेट" फ़ाइल के आउटपुट को SQL 1 में पाइप करना चाहता हूं >> इसलिए एक टेम्पलेट का उपयोग प्रश्न है, यह "छड़ी का गलत अंत" नहीं है। निर्यात चर और उन्हें किसी अन्य लिपि में गूंज सिर्फ सवाल का जवाब नहीं है सब पर
पियरे-ओलिवर Vares

0

बैकअप के साथ, संभावित रूप से कई फ़ाइलों के संपादन के स्थान पर।

  perl -e 's/\$\{([^}]+)\}/defined $ENV{$1} ? $ENV{$1} : ""/eg' \
    -i.orig \
    -p config/test/*

0

आप वर्तमान सुझावों से कुछ अधिक मजबूत चाहते हैं क्योंकि जब वे आपके (अभी के लिए) सीमित उपयोग के मामले में काम करते हैं, तो वे कई जटिल परिस्थितियों के लिए पर्याप्त नहीं होंगे।

आपको एक बेहतर रेंडरर की आवश्यकता है। आपको सर्वश्रेष्ठ रेंडरर की आवश्यकता है। आपको रेंडरेस्ट की आवश्यकता है!

टेम्पलेट दिया गया।

हैलो}}!

Daud:

$ व्यक्ति = बॉब ।/render template.txt

और आप आउटपुट देखेंगे

हैलो, बॉब!

इसे किसी फ़ाइल में रीडायरेक्ट करके फ़ाइल में लिखें:

$ व्यक्ति = बॉब ।/render template.txt> rend.txt

और यदि आप एक ऐसी स्क्रिप्ट का प्रतिपादन करते हैं, जिसमें $ {} चर हैं, जिन्हें आप प्रक्षेपित नहीं करना चाहते हैं, The Renderest ने आपको बिना कुछ और किए ही कवर कर लिया!

जाओ और https://github.com/relaxdiego/renderest पर अपनी प्रति प्राप्त करें

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