জটিল পাঠ্য ফাইলগুলিতে শেল ভেরিয়েবল কীভাবে প্রতিস্থাপন করবেন


89

আমার বেশ কয়েকটি পাঠ্য ফাইল রয়েছে যাতে আমি শেল ভেরিয়েবল ((VAR1 বা $ VAR2 উদাহরণস্বরূপ) প্রবর্তন করেছি।

আমি সেই ফাইলগুলি (একের পর এক) নিতে এবং সেগুলিকে নতুন ফাইলে সংরক্ষণ করতে চাই যেখানে সমস্ত ভেরিয়েবল প্রতিস্থাপন করা হত।

এটি করতে, আমি নিম্নলিখিত শেল স্ক্রিপ্ট ব্যবহার করেছি (স্ট্যাকওভারফ্লোতে পাওয়া যায়):

while read line
do
    eval echo "$line" >> destination.txt
done < "source.txt"

এটি খুব বেসিক ফাইলগুলিতে খুব ভাল কাজ করে।

তবে আরও জটিল ফাইলগুলিতে, "ইভাল" কমান্ডটি খুব বেশি করে:

  • "#" দিয়ে শুরু করা লাইনগুলি এড়িয়ে গেছে

  • এক্সএমএল ফাইলগুলি পার্সিংয়ের ফলে প্রচুর ত্রুটি হয়

এটা করতে একটি ভাল উপায় আছে কি? (শেল স্ক্রিপ্টে ... আমি জানি এটি খুব সহজেই পিঁপড়ার সাথে সম্পন্ন হয়)

আন্তরিক শুভেচ্ছা

উত্তর:


206

দেখছি, এটি আমার সিস্টেমে সক্রিয় হয় একটি envsubstকমান্ড রয়েছে যা গেটেক্সটেক্স-বেস প্যাকেজের অংশ।

সুতরাং, এটি এটিকে সহজ করে তোলে:

envsubst < "source.txt" > "destination.txt"

নোট আপনি উভয়ের জন্য একই ফাইল ব্যবহার করতে চান, আপনি moreutil এর ভালো কিছু ব্যবহার করতে হবে sponge, যেমন জনি Utahh দ্বারা প্রস্তাবিত: envsubst < "source.txt" | sponge "source.txt"। (কারণ শেল পুনর্নির্দেশ অন্যথায় ফাইলটি পড়ার আগে খালি করে দেবে))


4
দুর্দান্ত! তবে এটি শুধুমাত্র পরিবেশের ভেরিয়েবলের জন্য কাজ করে। আমার .sh স্ক্রিপ্টে ঘোষিত ভেরিয়েবলগুলির সাথে কীভাবে এটি কাজ করব?
বেন

12
@Ben: ব্যবহার 'রপ্তানি' প্রত্যেক পরিবর্তনশীল আপনি envsubst ব্যবহার করতে চান তাদের জন্য (envsubst কল করার আগে)
tlo


4
@User_mda যেখানে আউটপুট যায়
ডারোবার্ট

4
সতর্কতা: যদি ভেরিয়েবল বিস্তারের বাইরে source.txtকোনও $অক্ষর থাকে তবে envsubstএগুলি প্রতিস্থাপন করবে এবং এর থেকে বাঁচার কোনও উপায় নেই $। সাধারণ (কুরুচিপূর্ণ) কাজটি হ'ল export DOLLAR="$"
কোস

67

উত্তর 2 এর সাথে সম্পর্কিত, এনভ্যুবুস্ট সম্পর্কে আলোচনা করার সময়, আপনি জিজ্ঞাসা করেছিলেন:

আমার .sh স্ক্রিপ্টে ঘোষিত ভেরিয়েবলগুলির সাথে কীভাবে এটি কাজ করব?

উত্তরটি হ'ল কল করার আগে আপনার ভেরিয়েবলগুলি রফতানি করতে হবে envsubst

আপনি envsubst SHELL_FORMATআর্গুমেন্টটি ব্যবহার করে ইনপুটটিতে প্রতিস্থাপন করতে চান এমন পরিবর্তনশীল স্ট্রিংগুলিও সীমাবদ্ধ করতে পারেন (সাধারণ শেল ভেরিয়েবল মান - উদাহরণস্বরূপ ইনপুটটিতে স্ট্রিংয়ের অনিচ্ছাকৃত প্রতিস্থাপন এড়ানো $HOME)।

এই ক্ষেত্রে:

export VAR1='somevalue' VAR2='someothervalue'
MYVARS='$VAR1:$VAR2'

envsubst "$MYVARS" <source.txt >destination.txt

সব দৃষ্টান্ত প্রতিস্থাপন করবে $VAR1এবং $VAR2(এবং শুধুমাত্র VAR1এবং VAR2মধ্যে) source.txtসঙ্গে 'somevalue'এবং 'someothervalue'যথাক্রমে।


15
একক উদ্ধৃতি 'যা সেট করতে ব্যবহৃত হয় MYVARSতা গুরুত্বপূর্ণ
মার্ক Lakata

মনে রাখবেন যে, export, envsubst, বা কোনো interleaving কমান্ড ব্যর্থ হতে পারে যখন পাঠ্য থেকে বদলি বড়। রেফারেন্স।
বিশপ

@ram এর কারণ হল SHELL_FORMATযুক্তিটি বাদ দেওয়া (অর্থাত্‍ "$MYVARS") সমস্ত রফতানি ভেরিয়েবলগুলি প্রতিস্থাপনের কারণ। যদি এটি আপনার প্রয়োজন হয় তবে কোনও উদ্বেগের দরকার নেই।
থিয়াগো ফিগুয়েরো

14

আমি জানি যে এই বিষয়টি পুরানো, তবে ভেরিয়েবলগুলি রফতানি না করে আমার কাছে একটি সহজ কাজ সমাধান রয়েছে। অনলাইনার হতে পারে তবে আমি \লাইনের শেষ প্রান্তে বিভক্ত করতে পছন্দ করি ।

var1='myVar1'\
var2=2\
var3=${var1}\
envsubst '$var1,$var3' < "source.txt" > "destination.txt"

#         ^^^^^^^^^^^    ^^^^^^^^^^     ^^^^^^^^^^^^^^^
# define which to replace   input            output

envsubstপরিবেশের ভেরিয়েবল হিসাবে বিবেচনা করার জন্য ভেরিয়েবলগুলি একই লাইনে সংজ্ঞায়িত করা দরকার ।

'$var1,$var3'শুধুমাত্র কোন নির্দিষ্ট কাউকে প্রতিস্থাপন ঐচ্ছিক। একটি ইনপুট ফাইল ধারণ করুন ${VARIABLE_USED_BY_JENKINS}যা প্রতিস্থাপন করা উচিত নয়।


8
  1. আপনার ENV পরিবর্তনশীল সংজ্ঞায়িত করুন
$ export MY_ENV_VAR=congratulation
  1. নিম্নলিখিত বিষয়বস্তু সহ টেমপ্লেট ফাইল ( in.txt ) তৈরি করুন
$MY_ENV_VAR

আপনি আপনার সিস্টেম দ্বারা সংজ্ঞায়িত অন্যান্য সমস্ত ENV ভেরিয়েবলগুলি যেমন (লিনাক্সে) ER TERM, EL শেল, $ হোম ... ব্যবহার করতে পারেন

  1. আপনার in.txt ফাইলের সমস্ত এনভ-ভেরিয়েবলকে পুনঃস্থাপন করতে এবং ফলাফলটি out.txt এ লিখতে এই আদেশটি চালান
$ envsubst "`printf '${%s} ' $(sh -c "env|cut -d'=' -f1")`" < in.txt > out.txt
  1. Out.txt ফাইলের সামগ্রীটি পরীক্ষা করুন Check
$ cat out.txt

এবং আপনার "অভিনন্দন" দেখা উচিত।


0

আপনি যদি সত্যিই কেবল ব্যাশ (এবং সেড) ব্যবহার করতে চান তবে আমি আপনার প্রতিটি পরিবেশের ভেরিয়েবলগুলি ( setপসিক্স মোডে ফিরে আসার মাধ্যমে) যেতে পারব এবং সে থেকে সেডের জন্য একটি গুচ্ছ তৈরি করব -e 'regex', এটি দ্বারা সমাপ্ত হয়ে -e 's/\$[a-zA-Z_][a-zA-Z0-9_]*//g', তারপরে সমস্তটি পাস করবো সেড

পার্ল একটি ভাল কাজ করবে যদিও, আপনার অ্যারে হিসাবে পরিবেশগত ভারতে অ্যাক্সেস রয়েছে এবং আপনি এক্সিকিউটেবল প্রতিস্থাপন করতে পারেন যাতে আপনি কেবল একবারের সাথে কোনও পরিবেশের পরিবর্তনশীল মেলে।


কেন কেউ এই মত একটি উত্তর downvote হবে ??? -perl -pi -e 'foreach $key(sort keys %ENV){ s/\$$key/$ENV{$key}/g}' "$main_tf_file"
ইওর্ডান জর্জিভ

0

আসলে আপনাকে নিজের পরিবর্তন করতে readহবে read -rযা এটি ব্যাকস্ল্যাশগুলিকে উপেক্ষা করবে।

এছাড়াও, আপনার উদ্ধৃতি এবং ব্যাকস্ল্যাশগুলি এড়ানো উচিত। তাই

while read -r line; do
  line="${line//\\/\\\\}"
  line="${line//\"/\\\"}"
  line="${line//\`/\\\`}"
  eval echo "\"$line\""
done > destination.txt < source.txt

প্রসারণ করতে এখনও একটি ভয়ঙ্কর উপায়।


আসলে, খারাপ কোড থাকতে পারে এমন কোনও ফাইলের "ইওল" করার সময় সেই ঝুঁকিটি ছিল
বেন

0

সমস্ত প্রয়োজনীয় পরিবর্তনশীল রফতানি করুন এবং তারপরে পার্ল অনলাইনার ব্যবহার করুন use

TEXT=$(echo "$TEXT"|perl -wpne 's#\${?(\w+)}?# $ENV{$1} // $& #ge;')

এটি টেক্সটে উপস্থিত সমস্ত ENV ভেরিয়েবলকে প্রকৃত মানগুলির সাথে প্রতিস্থাপন করবে। উদ্ধৃতিগুলিও সংরক্ষিত আছে :)


0

যদি আপনি চান যে এনভ্যু ভেরিয়েবলগুলি আপনার উত্স ফাইলগুলিতে প্রতিস্থাপন করতে পারে তবে সমস্ত এনএনভি ভেরিয়েবলকে সে হিসাবে রাখলে আপনি নিম্নলিখিত কমান্ডটি ব্যবহার করতে পারেন:

envsubst "$(printf '${%s} ' $(env | sed 's/=.*//'))" < source.txt > destination.txt

কেবলমাত্র নির্দিষ্ট ভেরিয়েবলগুলি প্রতিস্থাপনের জন্য সিনট্যাক্সটি এখানে ব্যাখ্যা করা হয়েছে । উপরের কমান্ডটি একটি সাব-শেল ব্যবহার করে সমস্ত সংজ্ঞায়িত ভেরিয়েবলের তালিকা তৈরি করে এবং তারপর এটিতে প্রেরণ করেenvsubst

সুতরাং যদি একটি সংজ্ঞায়িত এনভ ভেরিয়েবল বলা হয় $NAME, এবং আপনার source.txtফাইলটি দেখতে এমন দেখাচ্ছে:

Hello $NAME
Your balance is 123 ($USD)

destination.txtহবে:

Hello Arik
Your balance is 123 ($USD)

লক্ষ্য করুন যে $NAMEপ্রতিস্থাপন করা হয়েছে এবং $USDকোনওটি অচিহ্নত রয়েছে


0

পার্ল বাইনারি কল করুন, অনুসন্ধান করুন এবং প্রতি লাইন মোডে প্রতিস্থাপন করুন (এক -pi) -eএকক উদ্ধৃতিতে পার্ল কোড (টি) চালিয়ে , যা বিশেষ হ্যাশগুলির কীগুলির উপর পুনরুক্তি করে যা %ENVএক্সপোর্ট করা ভেরিয়েবলের নামগুলি এবং রফতানি ভেরিয়েবল মানগুলি হিসাবে যুক্ত করে কীগুলির মান এবং প্রতিটি পুনরাবৃত্তির জন্য সরল একটি স্ট্রিং এর $<<key>>সাথে এটি প্রতিস্থাপন করে <<value>>

 perl -pi -e 'foreach $key(sort keys %ENV){ s/\$$key/$ENV{$key}/g}' file

কেভেট: যে ক্ষেত্রে দুটি বা ততোধিক ভার্সা একই স্ট্রিং দিয়ে শুরু হয় তার জন্য অতিরিক্ত যুক্তিযুক্ত হ্যান্ডলিং প্রয়োজন ...


-1

envsubst ঠিক যেমনটি আমি ব্যবহার করতে চেয়েছিলাম তেমন মনে হয়, কিন্তু -v বিকল্পটি আমাকে খানিকটা অবাক করে দিয়েছে।

ভাল envsubst < template.txtকাজ করার সময় , বিকল্পটির সাথে একই -vকাজ করছিল না:

$ cat /etc/redhat-release
Red Hat Enterprise Linux Server release 7.1 (Maipo)
$ envsubst -V
envsubst (GNU gettext-runtime) 0.18.2
Copyright (C) 2003-2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Bruno Haible.

আমি যেমন লিখেছি, এটি কাজ করছে না:

$ envsubst -v < template.txt
envsubst: missing arguments
$ cat template.txt | envsubst -v
envsubst: missing arguments

এটি কাজ করতে আমাকে এটি করতে হয়েছিল:

TEXT=`cat template.txt`; envsubst -v "$TEXT"

হতে পারে এটি কাউকে সাহায্য করে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.