আমি একটি "টেম্পলেট" ফাইলের আউটপুটটি মাইএসকিউএল এ পাইপ করতে চাই, ফাইলটি ${dbName}
ছেদ করার মতো ভেরিয়েবল রয়েছে । এই দৃষ্টান্তগুলি প্রতিস্থাপন করতে এবং আউটপুটটিকে স্ট্যান্ডার্ড আউটপুটে ডাম্প করতে কমান্ড লাইন ইউটিলিটিটি কী?
আমি একটি "টেম্পলেট" ফাইলের আউটপুটটি মাইএসকিউএল এ পাইপ করতে চাই, ফাইলটি ${dbName}
ছেদ করার মতো ভেরিয়েবল রয়েছে । এই দৃষ্টান্তগুলি প্রতিস্থাপন করতে এবং আউটপুটটিকে স্ট্যান্ডার্ড আউটপুটে ডাম্প করতে কমান্ড লাইন ইউটিলিটিটি কী?
উত্তর:
শেড !
প্রদত্ত টেমপ্লেট টেক্সট:
সংখ্যাটি $ {i is শব্দটি $ $ শব্দ}
আমাদের শুধু বলতে হবে:
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 like এর মতো পরিবর্তকের জন্য প্রতিস্থাপন করে এবং সংক্ষিপ্ত ওয়ান-লাইনার er
i=32 word=foo envsubst < template.txt
অবশ্যই যদি আমি এবং শব্দটি আপনার পরিবেশে থাকে তবে এটি ঠিক
envsubst < template.txt
আমার ম্যাক এটা দেখে মনে হচ্ছে এটা অংশ হিসাবে ইনস্টল করা ছিল gettext এর থেকে MacGPG2
অনুরূপ প্রশ্নের মোগসি থেকে সমাধানের জন্য এখানে একটি উন্নতি জানানো হয়েছে , আমার সমাধানটির জন্য আপনাকে ডাবল উদ্ধৃতিগুলি মোগিসির করা প্রয়োজন হয় না, তবে তার একটি লাইনার!
eval "cat <<EOF
$(<template.txt)
EOF
" 2> /dev/null
এই দুটি সমাধান শক্তি আপনি শুধুমাত্র স্বাভাবিকভাবে $ ((...)) যে ঘটবে না কয়েক শেল প্রসারণও ধরনের, `...` পেতে, এবং $ (...), যদিও ব্যাকস্ল্যাশ হয় একটি চরিত্রটি এখানে রক্ষা করুন, তবে আপনাকে ভাবতে হবে না যে পার্সিংয়ে একটি ত্রুটি রয়েছে এবং এটি একাধিক লাইন ঠিক জরিমানা করে।
envsubst
পেয়েছি যদি আপনার এনভার্স রফতানি না হয় তবে কাজ করে না।
envsubst
, এর নাম অনুসারে, কেবল পরিবেশের ভেরিয়েবলগুলি সনাক্ত করে , শেল ভেরিয়েবলগুলি নয়। এটি envsubst
একটি জিএনইউ ইউটিলিটি, এবং অতএব ইনস্টল করা বা সমস্ত প্ল্যাটফর্মগুলিতে উপলব্ধ নয় তা লক্ষণীয় ।
ব্যবহার /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
ইনপুট সমস্ত কমান্ড কার্যকর করা হবে। যদি টেমপ্লেটটি হয়: "শব্দগুলি হল; আরএম -আরএফ OME হোম" আপনি ফাইলগুলি আলগা করুন।
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 টেমপ্লেট। টেক্সট 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-substedia.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
আপনি যদি পার্ল ব্যবহারের জন্য উন্মুক্ত হন তবে তা আমার পরামর্শ হবে। যদিও সম্ভবত কিছু সেড এবং / বা এডাব্লুকে বিশেষজ্ঞ রয়েছে যা সম্ভবত এটি কীভাবে আরও সহজভাবে করতে হয় তা জানেন। যদি আপনার প্রতিস্থাপনের জন্য কেবলমাত্র 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
আপনার জন্য বিকল্পটি নেওয়ার শেলটি এখানে পাওয়ার একটি উপায়, যেন ফাইলের বিষয়বস্তু পরিবর্তে ডাবল কোটের মধ্যে টাইপ করা থাকে।
বিষয়বস্তু সহ টেমপ্লেট.টেক্সটের উদাহরণ ব্যবহার করে:
The number is ${i}
The word is ${word}
নিম্নলিখিত লাইনটি শেলটিকে টেমপ্লেট.টিএসটিএসটির বিষয়বস্তুগুলিকে বিভক্ত করবে এবং ফলাফলটি স্ট্যান্ডার্ড আউট থেকে লিখবে।
i='1' word='dog' sh -c 'echo "'"$(cat template.txt)"'"'
ব্যাখ্যা:
i
এবং word
গৃহীত হয় এনভায়রনমেন্ট ভেরিয়েবল এর মৃত্যুদন্ড থেকে scopped 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
রেজেকেক্স বা ব্যবহারের চেয়ে অনেক বেশি নিরাপদ এবং সহজsed
cat
এবং ব্যবহার <my-file.conf.template
করা আরও ভাল যাতে আপনি sigil
কোনও ফিফোর পরিবর্তে একটি আসল ফাইল হ্যান্ডেল দেন।
একই জিনিসটি ভাবতে গিয়ে আমি এই থ্রেডটি পেয়েছি। এটি আমাকে এতে অনুপ্রাণিত করেছে (ব্যাকটিক্সগুলির সাথে সাবধানতা অবলম্বন করুন)
$ echo $MYTEST
pass!
$ cat FILE
hello $MYTEST world
$ eval echo `cat FILE`
hello pass! world
$(cat file)
হয়$(< file)
eval echo "\"$(cat FILE)\""
তবে ইনপুটটিতে ডাবল উদ্ধৃতিগুলি ফেলে দেওয়া হবে এমনটি এখনও কম হতে পারে।
`…`
বা $(…)
) ব্যবহারের কারণে স্বেচ্ছাচারিত আদেশগুলি কার্যকর করতে দেয় eval
।
এখানে প্রচুর পছন্দসই, তবে আমি বুঝতে পেরেছি যে আমি গাদা আমার উপর টাসছি। এটি পার্ল ভিত্তিক, কেবল $ {... form ফর্মের ভেরিয়েবলগুলিকে লক্ষ্য করে, ফাইলটিকে একটি আর্গুমেন্ট হিসাবে প্রক্রিয়া করতে নেয় এবং রূপান্তরিত ফাইলকে স্টাডআউটে আউটপুট দেয়:
use Env;
Env::import();
while(<>) { $_ =~ s/(\${\w+})/$1/eeg; $text .= $_; }
print "$text";
অবশ্যই আমি সত্যিই একজন পারল ব্যক্তি নই, সুতরাং সহজেই মারাত্মক ত্রুটি হতে পারে (যদিও এটি আমার পক্ষে কাজ করে)।
Env::import();
লাইনটি ফেলে দিতে পারেন - আমদানি দ্বারা বোঝানো হয় use
। এছাড়াও, আমি প্রথমে স্মৃতিতে পুরো আউটপুট তৈরি না করার পরামর্শ দিই: কেবল লুপের অভ্যন্তরের print;
পরিবর্তে ব্যবহার করুন $text .= $_;
এবং পোস্ট-লুপ print
কমান্ডটি ড্রপ করুন ।
কনফিগারেশন ফাইল ফর্ম্যাটের আপনার নিয়ন্ত্রণ থাকলে এটি ব্যাশ নিজেই করা যায়। আপনার কনফিগারেশন ফাইলটি সাবস্কেল না করে কেবল ("।") উত্সের প্রয়োজন। এটি নিশ্চিত করে যে ভেরিয়েবলগুলি বর্তমান শেলটির প্রসঙ্গে তৈরি করা হয়েছে (এবং বিদ্যমান থাকা অব্যাহত থাকবে) পরিবর্তে সাব-শেল (যেখানে ভেরিয়েবল অদৃশ্য হয়ে যায় যখন সাব-শেল প্রস্থান করে)।
$ 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
তারপরে মাইএসকিউএল এবং ভয়েলায় go.bash এর আউটপুটটি পাইপ করুন, আশা করি আপনি আপনার ডাটাবেসটি ধ্বংস করবেন না :-)।
go.bash
), আপনি লাঠিটির ভুল শেষ পেয়েছেন - এগুলি সমাধানের অংশ নয়, তারা কেবল ভেরিয়েবলগুলি দেখানোর এক উপায়'re সঠিকভাবে সেট করুন।