मैं MySQL में एक "टेम्पलेट" फ़ाइल के आउटपुट को पाइप करना चाहता हूं, फ़ाइल जिसमें चौराहे जैसे चर हैं ${dbName}
। इन उदाहरणों को बदलने और आउटपुट को मानक आउटपुट में डंप करने के लिए कमांड लाइन उपयोगिता क्या है?
मैं MySQL में एक "टेम्पलेट" फ़ाइल के आउटपुट को पाइप करना चाहता हूं, फ़ाइल जिसमें चौराहे जैसे चर हैं ${dbName}
। इन उदाहरणों को बदलने और आउटपुट को मानक आउटपुट में डंप करने के लिए कमांड लाइन उपयोगिता क्या है?
जवाबों:
सैड !
टेम्पलेट दिया गया।
संख्या $ {i} है शब्द $ {शब्द} है
हमें सिर्फ यह कहना है:
sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.txt
-e
एक ही sed
आह्वान के लिए कई तर्क पारित करने के लिए टिप के लिए जोनाथन लेफ़लर का धन्यवाद ।
cat
। आप सभी की जरूरत है sed -e "s/\${i}/1/" -e "s/\${word}/dog/" template.text
।
sed
बचने वाले पाठ की अपेक्षा करेंगे, जो एक परेशानी है।
यहाँ एक ऐसे ही सवाल पर यॉट्सएटा से एक समाधान है जो केवल $ VAR या $ {VAR} जैसे चर के लिए प्रतिस्थापन करता है, और एक संक्षिप्त एक-लाइनर है
i=32 word=foo envsubst < template.txt
बेशक अगर मैं और शब्द आपके वातावरण में हैं, तो यह सिर्फ है
envsubst < template.txt
अपने Mac पर ऐसा लगता है कि यह के भाग के रूप स्थापित किया गया था gettext और से MacGPG2
इसी तरह के एक सवाल पर मोगी से समाधान में सुधार किया गया है , मेरे समाधान के लिए आपको दोहरे उद्धरण चिह्नों की आवश्यकता नहीं है, मोगी का क्या है, लेकिन उनका एक लाइनर है!
eval "cat <<EOF
$(<template.txt)
EOF
" 2> /dev/null
इन दो समाधान पर शक्ति है कि आप केवल सामान्य रूप से $ ((...)) कि नहीं होती है कुछ खोल विस्तार के प्रकार, `` ... मिलता है, और $ (...), हालांकि बैकस्लैश है एक यहाँ से बच चरित्र, लेकिन आप चिंता करने की ज़रूरत नहीं है कि पार्सिंग में एक बग है, और यह कई लाइनों को ठीक करता है।
envsubst
अगर आपके दूत निर्यात नहीं होते हैं तो मैं नंगे काम नहीं कर रहा हूँ ।
envsubst
, जैसा कि इसके नाम से पता चलता है, केवल पर्यावरण चर को पहचानता है , शेल चर को नहीं । यह भी ध्यान देने योग्य है कि envsubst
एक GNU उपयोगिता है, और इसलिए सभी प्लेटफार्मों पर पूर्वस्थापित या उपलब्ध नहीं है।
का उपयोग करें /bin/sh
। एक छोटी सी शेल स्क्रिप्ट बनाएं जो चर सेट करता है, और फिर शेल का उपयोग करके टेम्पलेट को पार्स करें। ऐसा ही (नई कहानियों को सही ढंग से संभालने के लिए संपादित करें):
the number is ${i}
the word is ${word}
#!/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
bash
इनपुट में सभी कमांड निष्पादित किए जाएंगे। यदि टेम्प्लेट है: "शब्द है, rm -rf $ HOME" तो आप फाइलें ढीली कर देंगे।
read
कमांड, जैसा कि लिखा गया है, प्रत्येक पंक्ति से व्हाट्सएप को अग्रणी और पीछे ले जाता है और चार्ट को खाता है \
। (ग) केवल इस तरह से यदि आप पूरी तरह से छोड़ देते हैं। इनपुट पर भरोसा करें या नियंत्रित करें, क्योंकि इनपुट में एम्बेडेड कमांड प्रतिस्थापन ( `…`
या $(…)
) उपयोग के कारण मनमाने आदेशों के निष्पादन की अनुमति देता है eval
। अंत में, एक छोटा सा मौका है जो echo
अपने कमांड लाइन विकल्पों में से एक के लिए एक पंक्ति की शुरुआत में गलती करता है।
मैं इस बारे में फिर से सोच रहा था, हाल ही में ब्याज दिया गया था, और मुझे लगता है कि जिस टूल के बारे में मैं मूल रूप से सोच रहा था m4
, वह ऑटोलूलस के लिए मैक्रो प्रोसेसर था । इसलिए आपके द्वारा निर्दिष्ट चर के बजाय, आप उपयोग करेंगे:
$echo 'I am a DBNAME' | m4 -DDBNAME="database name"
envsubst
इस सरल चर प्रतिस्थापन / अस्थायी उपयोग के लिए उपयोग करूंगा , जैसा कि अन्य उत्तरों में वर्णित है। m4
एक महान उपकरण है, लेकिन यह बहुत अधिक सुविधाओं के साथ एक पूर्ण विकसित प्रीप्रोसेसर है और इस प्रकार जटिलता की आवश्यकता नहीं है अगर आप बस कुछ चर को बदलना चाहते हैं।
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
`…`
या $(…)
) उपयोग के कारण मनमाने आदेशों के निष्पादन की अनुमति देता है eval
, और उपयोग के कारण शेल कोड का प्रत्यक्ष निष्पादन source
। इसके अलावा, इनपुट में दोहरे उद्धरण चुपचाप खारिज कर दिए जाते हैं, और echo
इसके कमांड लाइन विकल्पों में से एक के लिए एक पंक्ति की शुरुआत में गलती हो सकती है।
यहां एक मजबूत बैश फ़ंक्शन है - उपयोग करने के बावजूद 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
नियंत्रण वर्ण मौजूद नहीं हैं, क्योंकि वे वर्ण हैं। आंतरिक रूप से उपयोग किया जाता है - चूंकि फ़ंक्शन पाठ को संसाधित करता है , इसलिए यह एक सुरक्षित धारणा होनी चाहिए।
eval
करने के साथ भी यह उपयोग करने के लिए बहुत सुरक्षित है।
"
ठीक से बचकर !)
${FOO:-bar}
यदि आप इसे सेट करते हैं तो आपको गुम चर या केवल कुछ आउटपुट के लिए चूक प्रदान करने देंगे ${HOME+Home is ${HOME}}
। मुझे थोड़ा विस्तार से संदेह है कि यह लापता चर के लिए निकास कोड भी वापस कर सकता है, ${FOO?Foo is missing}
लेकिन वर्तमान में tldp.org/LDP/abs/html/parameter-substitution.html के पास इनकी सूची नहीं है अगर इसमें मदद मिलती है
बनाएँ 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
$(rm -rf ~)
, तो आप उसे कोड के रूप में चला रहे हैं।
eval "echo \"$(cat $1)\""
बहुत अच्छा काम करता है !
पूर्व के उत्तर के आधार पर पर्ल के साथ यहां मेरा समाधान, पर्यावरण चर की जगह:
perl -p -e 's/\$\{(\w+)\}/(exists $ENV{$1}?$ENV{$1}:"missing variable $1")/eg' < infile > outfile
यदि आप पर्ल का उपयोग करने के लिए खुले हैं , तो यह मेरा सुझाव होगा। हालांकि शायद कुछ सेड और / या 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
यहां आपके लिए प्रतिस्थापन करने के लिए शेल प्राप्त करने का एक तरीका है, जैसे कि फ़ाइल की सामग्री को दोहरे उद्धरण चिह्नों के बजाय टाइप किया गया था।
सामग्री के साथ 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 "
निष्पादित किया जा सकता है।
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
\$(date)
while IFS= read -r line; do
रूप में उपयोग करें read
, अन्यथा आप प्रत्येक इनपुट लाइन से व्हाट्सएप को अग्रणी और पीछे छोड़ देंगे। इसके अलावा, echo
इसके कमांड लाइन विकल्पों में से एक के लिए एक लाइन की शुरुआत में गलती हो सकती है, इसलिए इसका उपयोग करना बेहतर है printf '%s\n'
। अंत में, यह दोहरे उद्धरण के लिए सुरक्षित है ${1}
।
मैं सिगिल जैसे कुछ का उपयोग करने का सुझाव दूंगा : https://github.com/gliderlabs/sigil
यह एकल बाइनरी के लिए संकलित है, इसलिए सिस्टम पर स्थापित करना बेहद आसान है।
तो आप निम्न की तरह एक साधारण एक लाइनर कर सकते हैं:
cat my-file.conf.template | sigil -p $(env) > my-file.conf
यह eval
regex या का उपयोग करके की तुलना में बहुत सुरक्षित हैsed
cat
और उपयोग करने के लिए बेहतर है <my-file.conf.template
ताकि आप sigil
एक FIFO के बजाय एक वास्तविक फ़ाइल हैंडल दें।
मैंने इसी बात को सोचते हुए यह धागा पाया। इसने मुझे इसके लिए प्रेरित किया (बैकटिक्स के साथ सावधान)
$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world
$(cat file)
है$(< file)
eval echo "\"$(cat FILE)\""
लेकिन इनपुट में उस दोहरे उद्धरण में अभी भी कमी आ सकती है।
`…`
या $(…)
) उपयोग के कारण मनमाने आदेशों के निष्पादन की अनुमति देते हैं eval
।
यहाँ बहुत सारे विकल्प हैं, लेकिन मुझे लगा कि मैं ढेर पर अपना टॉस करूँगा। यह पर्ल आधारित है, केवल फॉर्म $ {...} के चर को लक्षित करता है, फ़ाइल को एक तर्क के रूप में संसाधित करने के लिए लेता है और stdout पर परिवर्तित फ़ाइल को आउटपुट करता है:
use Env;
Env::import();
while(<>) { $_ =~ s/(\${\w+})/$1/eeg; $text .= $_; }
print "$text";
बेशक मैं वास्तव में एक प्रति व्यक्ति नहीं हूं, इसलिए आसानी से एक घातक दोष हो सकता है (हालांकि मेरे लिए काम करता है)।
Env::import();
लाइन छोड़ सकते हैं - आयात द्वारा निहित है use
। इसके अलावा, मेरा सुझाव है कि पहले मेमोरी में पूरे आउटपुट का निर्माण न करें: केवल लूप print;
के $text .= $_;
अंदर का उपयोग करें , और पोस्ट-लूप print
कमांड को छोड़ दें ।
यदि आप कॉन्फ़िगरेशन फ़ाइल स्वरूप का नियंत्रण रखते हैं, तो इसे अपने आप ही 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 और वॉइला में पाइप करें, उम्मीद है कि आप अपने डेटाबेस को नष्ट नहीं करेंगे :-)।
go.bash
) में इको स्टेटमेंट के बारे में बात कर रहे हैं , तो आपको स्टिक का गलत अंत मिल गया है - वे समाधान का हिस्सा नहीं हैं, वे सिर्फ यह दिखाने का एक तरीका है कि चर रहे हैं सही ढंग से सेट करें।
आप वर्तमान सुझावों से कुछ अधिक मजबूत चाहते हैं क्योंकि जब वे आपके (अभी के लिए) सीमित उपयोग के मामले में काम करते हैं, तो वे कई जटिल परिस्थितियों के लिए पर्याप्त नहीं होंगे।
आपको एक बेहतर रेंडरर की आवश्यकता है। आपको सर्वश्रेष्ठ रेंडरर की आवश्यकता है। आपको रेंडरेस्ट की आवश्यकता है!
टेम्पलेट दिया गया।
हैलो}}!
Daud:
$ व्यक्ति = बॉब ।/render template.txt
और आप आउटपुट देखेंगे
हैलो, बॉब!
इसे किसी फ़ाइल में रीडायरेक्ट करके फ़ाइल में लिखें:
$ व्यक्ति = बॉब ।/render template.txt> rend.txt
और यदि आप एक ऐसी स्क्रिप्ट का प्रतिपादन करते हैं, जिसमें $ {} चर हैं, जिन्हें आप प्रक्षेपित नहीं करना चाहते हैं, The Renderest ने आपको बिना कुछ और किए ही कवर कर लिया!
जाओ और https://github.com/relaxdiego/renderest पर अपनी प्रति प्राप्त करें