ব্যাশে স্ক্রিপ্টে ঘোষিত ভেরিয়েবলগুলি কীভাবে তালিকাভুক্ত করবেন?


99

আমার স্ক্রিপ্টে ব্যাশে, প্রচুর ভেরিয়েবল রয়েছে এবং ফাইলগুলিতে সেভ করার জন্য আমাকে কিছু তৈরি করতে হবে। আমার প্রশ্নটি হ'ল কীভাবে আমার স্ক্রিপ্টে ঘোষিত সমস্ত ভেরিয়েবলগুলি তালিকাভুক্ত করবেন এবং এর মতো তালিকা পাবেন:

VARIABLE1=abc
VARIABLE2=def
VARIABLE3=ghi

উত্তর:


151

set ভেরিয়েবলগুলি আউটপুট দেবে, দুর্ভাগ্যক্রমে এটি ফাংশনগুলিও সংজ্ঞায়িত করে আউটপুট দেবে।

ভাগ্যক্রমে পসিক্স মোডটি কেবল ভেরিয়েবলকে আউটপুট করে:

( set -o posix ; set ) | less

পাইপিং করা lessবা আপনি যেখানে অপশনগুলি চান সেখানে যেতে হবে red

সুতরাং কেবল স্ক্রিপ্টে ভেরিয়েবলগুলি ঘোষণা করতে:

( set -o posix ; set ) >/tmp/variables.before
source script
( set -o posix ; set ) >/tmp/variables.after
diff /tmp/variables.before /tmp/variables.after
rm /tmp/variables.before /tmp/variables.after

(বা কমপক্ষে কিছু :-) এর উপর ভিত্তি করে)


আমি পোস্ট করার সময় আপনি সম্পাদনা করেছিলেন। -o posixএখন একটি ভিন্ন সঙ্গে ভাল কল শুধুমাত্র ভেরিয়েবল থাকবে।
ইজপিজ

8
অস্থায়ী ফাইল ব্যবহার না করেই: VARS="`set -o posix ; set`"; source script; SCRIPT_VARS="`grep -vFe "$VARS" <<<"$(set -o posix ; set)" | grep -v ^VARS=`"; unset VARS;। এটি ভার্সিয়াকে একটি রেডি-টু-সেভ ফরমেটে আউটপুট দেবে। তালিকাতে স্ক্রিপ্টটি পরিবর্তিত হওয়া ভেরিয়েবলগুলি অন্তর্ভুক্ত করা হবে (এটি পছন্দসই কিনা তা নির্ভর করে)
ivan_pozdeev

4
@ এরিক অ্যারোনস্টি আপনি যদি একটি পরিবেশের সাথে পুনরায় তৈরি করতে সক্ষম হতে চান তবে আপনার sourceআউটপুট দিয়ে তা করতে সক্ষম হবেন declare -p
ছয়

4
আপনি টেম্প ফাইল ব্যবহার অবলম্বন না পরিবর্তন (অথবা কোন অনুরূপ কমান্ড) সঙ্গে আগে ও পরে একটি পরিবেশ তুলনা করতে চান, আপনি নিম্নলিখিত সঙ্গে এটি করতে পারেন:before=$(set -o posix; set); dosomestuff; diff <(echo "$before") <(set -o posix; set)
ছয়

4
@ কায়সার না, আমি কেবল খালি খালি অ্যারে চেষ্টা করেছি। খালি অ্যারেগুলির ক্ষেত্রে আপনার ঠিক আছে - সেগুলি মুদ্রিত হয় না।
সোসোইই

41
compgen -v

এটি স্থানীয় সহ সমস্ত ভেরিয়েবলের তালিকা করে। আমি ভেরিয়েবলগুলির তালিকা পান যাঁর নাম একটি নির্দিষ্ট প্যাটার্নের সাথে মেলে এবং এটি আমার স্ক্রিপ্টে ব্যবহার করে শিখেছি ।


4
দুঃখের বিষয়, compgen -vস্থানীয়ভাবে আনসেট করা বৈশ্বিক পরিবর্তনগুলিও তালিকাভুক্ত করে lists নিশ্চিত নয় যে এটি কোনও দীর্ঘস্থায়ী বাগ বা পছন্দসই আচরণ।
মিশা গার্নি

11
for i in _ {a..z} {A..Z}; do eval "echo \${!$i@}" ; done | xargs printf "%s\n"

এটি অবশ্যই সমস্ত শেল ভেরিয়েবলের নাম মুদ্রণ করবে। কোন ফাইলটি ভেরিয়েবলগুলি নতুন (অন্য উত্তরে বর্ণিত হিসাবে) আলাদা করার জন্য আপনি "সেট" এর মতো আপনার ফাইলের উত্সাহ দেওয়ার আগে এবং পরে একটি তালিকা পেতে পারেন। তবে মনে রাখবেন ডিফের সাথে এই ধরনের ফিল্টারিং আপনার প্রয়োজনীয় কিছু ভেরিয়েবলগুলি ফিল্টার করতে পারে তবে আপনার ফাইলটি উত্সাহ দেওয়ার আগে উপস্থিত ছিল।

আপনার ক্ষেত্রে, যদি আপনি জানেন যে আপনার ভেরিয়েবলের নামগুলি "VARIABLE" দিয়ে শুরু হয়, তবে আপনি আপনার স্ক্রিপ্টটি উত্স করে এবং করতে পারেন:

for var in ${!VARIABLE@}; do
   printf "%s%q\n" "$var=" "${!var}"
done

আপডেট: খাঁটি BASH সমাধানের জন্য (কোনও বাহ্যিক আদেশ ব্যবহার করা হয়নি):

for i in _ {a..z} {A..Z}; do
   for var in `eval echo "\\${!$i@}"`; do
      echo $var
      # you can test if $var matches some criteria and put it in the file or ignore
   done 
done

4
+1 এবং একটি অনিলিয়ার সংস্করণ (একক ইভাল সহ):eval "printf '%q\n' $(printf ' "${!%s@}"' _ {a..z} {A..Z})"
নেট

4

উপরের কয়েকটি উত্তরের ভিত্তিতে, এটি আমার পক্ষে কাজ করেছে:

before=$(set -o posix; set | sort);

উত্স ফাইল :

comm -13 <(printf %s "$before") <(set -o posix; set | sort | uniq) 

3

আপনি যদি পোস্ট-প্রক্রিয়া করতে পারেন, (যেমন ইতিমধ্যে উল্লিখিত) আপনি কেবলমাত্র setআপনার স্ক্রিপ্টের শুরু এবং শেষের দিকে (প্রতিটি পৃথক পৃথক ফাইলে) কল দিতে পারেন এবং দুটি ফাইলে আলাদা করতে পারেন। বুঝতে পারেন যে এটিতে এখনও কিছু শব্দ থাকবে।

আপনি এই প্রোগ্রামক্রমেও করতে পারেন। আউটপুটটিকে কেবল আপনার বর্তমান সুযোগে সীমাবদ্ধ করতে, আপনাকে একটি মোড়কটি পরিবর্তনশীল তৈরিতে প্রয়োগ করতে হবে। উদাহরণ স্বরূপ

store() {
    export ${1}="${*:2}"
    [[ ${STORED} =~ "(^| )${1}($| )" ]] || STORED="${STORED} ${1}"
}

store VAR1 abc
store VAR2 bcd
store VAR3 cde

for i in ${STORED}; do
    echo "${i}=${!i}"
done

যা ফলন দেয়

VAR1=abc
VAR2=bcd
VAR3=cde

2

এখানে @ জিঙ্কগোফর উত্তরের মতো কিছু রয়েছে তবে @Tino বা @ ডিজেক্লেটন দ্বারা চিহ্নিত সমস্যাগুলি ছাড়াই এবং @ ডগলাসলিডারের চালাক set -o posixবিটের চেয়ে আরও শক্তিশালী :

+ function SOLUTION() { (set +o posix; set) | sed -ne '/^\w\+=/!q; p;'; }

পার্থক্যটি হ'ল এই সমাধানটি প্রথম অ-পরিবর্তনশীল প্রতিবেদনের পরে যেমন STOPS, যেমন প্রথম ফাংশন দ্বারা প্রতিবেদন করা set

বিটিডাব্লু: "টিনো" সমস্যাটি সমাধান হয়েছে। যদিও পসিক্স বন্ধ করা আছে এবং ফাংশনগুলি দ্বারা রিপোর্ট করা হয়েছে set, sed ...সমাধানের অংশটি কেবলমাত্র (যেমন VAR=VALUEলাইনগুলি) মাধ্যমে পরিবর্তনশীল প্রতিবেদনগুলিকে অনুমতি দেয় । বিশেষত, তাত্পর্যপূর্ণভাবে এটিকে আউটপুট তৈরি A2করে না

+ function a() { echo $'\nA2=B'; }; A0=000; A9=999; 
+ SOLUTION | grep '^A[0-9]='
A0=000
A9=999

এবং: "দেজেক্লেটন" সমস্যার সমাধান হয়েছে (পরিবর্তনশীল মানগুলিতে এম্বেড করা নিউলাইনগুলি আউটপুটকে ব্যাহত করে না - প্রত্যেকে VAR=VALUEএকটি একক আউটপুট লাইন পান):

+ A1=$'111\nA2=222'; A0=000; A9=999; 
+ SOLUTION | grep '^A[0-9]='
A0=000
A1=$'111\nA2=222'
A9=999

দ্রষ্টব্য: @ ডগলাসলিডার সরবরাহিত সমাধানটি "দেজাইক্লেটন" সমস্যায় ভুগছে (এম্বেডড নিউলাইনগুলি সহ মানগুলি)। নীচে, এটি A1ভুল এবং একেবারে A2প্রদর্শন করা উচিত নয়।

$ A1=$'111\nA2=222'; A0=000; A9=999; (set -o posix; set) | grep '^A[0-9]='
A0=000
A1='111
A2=222'
A9=999

শেষ পর্যন্ত: আমি মনে করি না bashবিষয়গুলির সংস্করণ , তবে এটি হতে পারে। আমি এইটি দিয়ে আমার পরীক্ষা / বিকাশ করেছি:

$ bash --version
GNU bash, version 4.4.12(1)-release (x86_64-pc-msys)

পোস্ট-স্ক্রিপ্ট: ওপিতে অন্যান্য প্রতিক্রিয়াগুলির কয়েকটি দেওয়া, আমি <100% নিশ্চিত রয়েছি যে set সর্বদা মানের মধ্যে \nনিউলাইনগুলিকে রূপান্তর করে , যা এই সমাধান "দেজয়ক্লেটন" সমস্যা এড়াতে নির্ভর করে। সম্ভবত এটি একটি আধুনিক আচরণ? অথবা একটি সংকলন-সময়ের প্রকরণ? অথবা একটি set -oবা shoptবিকল্প সেটিং? যদি আপনি এই ধরনের বৈচিত্রগুলি জানেন তবে দয়া করে একটি মন্তব্য যুক্ত করুন ...


0

একটি স্ক্রিপ্ট ব্যবহার করে দেখুন (এটিকে "ls_vars" বলতে দিন):

  #!/bin/bash
  set -a
  env > /tmp/a
  source $1
  env > /tmp/b
  diff /tmp/{a,b} | sed -ne 's/^> //p'

chmod + x এটি, এবং:

  ls_vars your-script.sh > vars.files.save

0

সুরক্ষা দৃষ্টিকোণ থেকে, নিম্নলিখিত সম্ভাব্য সুরক্ষা ত্রুটির কারণে @ আকোস্টাডিনভের উত্তর বা @ জুভেনএক্সু এর উত্তর হ'ল setকমান্ডের অরক্ষিত আউটপুটটির উপর নির্ভর করা পছন্দনীয় :

#!/bin/bash

function doLogic()
{
    local COMMAND="${1}"
    if ( set -o posix; set | grep -q '^PS1=' )
    then
        echo 'Script is interactive'
    else
        echo 'Script is NOT interactive'
    fi
}

doLogic 'hello'   # Script is NOT interactive
doLogic $'\nPS1=' # Script is interactive

উপরের ফাংশন doLogicব্যবহার setপরিবর্তনশীল উপস্থিতি চেক করতে PS1কিনা তা নির্ধারণ করতে স্ক্রিপ্ট ইন্টারেক্টিভ বা নয় (কিছু মনে করবেন না যদি এই শ্রেষ্ঠ উপায় যে লক্ষ্যে পৌঁছনোর জন্য নয়; এই মাত্র একটি উদাহরণ।)

তবে এর আউটপুট set কাঠামোগত নয়, যার অর্থ একটি নিউলাইন রয়েছে এমন কোনও পরিবর্তনশীল ফলাফলগুলি সম্পূর্ণ দূষিত করতে পারে।

এটি অবশ্যই একটি সম্ভাব্য সুরক্ষা ঝুঁকি। পরিবর্তে, পরোক্ষ পরিবর্তনশীল নাম বিস্তৃতির জন্য পারেন ব্যাশ সমর্থন, বা ব্যবহারের compgen -v


0

এটি চেষ্টা করুন: set | egrep "^\w+="( | lessপাইপিং সহ বা ছাড়া )

প্রথম প্রস্তাবিত সমাধান, ( set -o posix ; set ) | lessকাজ করে তবে একটি অসুবিধা রয়েছে: এটি কন্ট্রোল কোডগুলিকে টার্মিনালে প্রেরণ করে, তাই সেগুলি সঠিকভাবে প্রদর্শিত হয় না। সুতরাং উদাহরণস্বরূপ, যদি (সম্ভবত) থাকে কোনও IFS=$' \t\n'পরিবর্তনশীল থাকে তবে আমরা দেখতে পাই:

IFS='
'

…পরিবর্তে.

আমার egrepসমাধান এটিকে (এবং শেষ পর্যন্ত অন্যান্য সাদৃশ্যগুলি) সঠিকভাবে প্রদর্শন করে।


এটি 8 বছর হয়েছে, আপনি জানেন
লরিয়াস

ডাউনভোটেড কারণ এটি সাধারণ ভুল bash -c $'a() { echo "\nA=B"; }; unset A; set | egrep "^\w+="' | grep ^A প্রদর্শন A=B"-> ব্যর্থ!
টিনো

অদ্ভুত পরীক্ষাটি কেবল "_" (পূর্ববর্তী কমান্ডের সর্বশেষ যুক্তি) সিউডো-ভেরিয়েবলকে বোঝায় তবে অন্যদের, বিশেষত আইএফএসে ব্যর্থ হয় না। এটিকে "বাশ-সি" এর অধীনে চালানো তাত্পর্যপূর্ণ করে তুলতে পারে না। কমপক্ষে ডাউনভোটিংয়ের পরিবর্তে আপনার নিরপেক্ষ থাকা উচিত ছিল।
জিঙ্গকোফ্রি

0

আমি সম্ভবত উত্তরটি আগে চুরি করেছি ... যাইহোক মজাদার হিসাবে কিছুটা আলাদা:

    ##
    # usage source bin/nps-bash-util-funcs
    # doEchoVars
    doEchoVars(){

        # if the tmp dir does not exist
        test -z ${tmp_dir} && \
        export tmp_dir="$(cd "$(dirname $0)/../../.."; pwd)""/dat/log/.tmp.$$" && \
        mkdir -p "$tmp_dir" && \
        ( set -o posix ; set )| sort >"$tmp_dir/.vars.before"


        ( set -o posix ; set ) | sort >"$tmp_dir/.vars.after"
        cmd="$(comm -3 $tmp_dir/.vars.before $tmp_dir/.vars.after | perl -ne 's#\s+##g;print "\n $_ "' )"
        echo -e "$cmd"
    } 

0

printenvকমান্ড প্রয়োগ করুন:

printenv সমস্ত মুদ্রণ environment variablesতাদের মান সহ ।

শুভকামনা ...


0

এটি করার সহজ উপায় হ'ল আপনার স্ক্রিপ্টটি চালানোর আগে সিস্টেম এনভায়রনমেন্ট ভেরিয়েবলগুলি সেট করে বাশ স্ট্রাইক মোড ব্যবহার করা এবং কেবল আপনার স্ক্রিপ্টের ধরণের বাছাই করতে ডিফ ব্যবহার করা:

# Add this line at the top of your script :
set > /tmp/old_vars.log

# Add this line at the end of your script :
set > /tmp/new_vars.log

# Alternatively you can remove unwanted variables with grep (e.g., passwords) :
set | grep -v "PASSWORD1=\|PASSWORD2=\|PASSWORD3=" > /tmp/new_vars.log

# Now you can compare to sort variables of your script :
diff /tmp/old_vars.log /tmp/new_vars.log | grep "^>" > /tmp/script_vars.log

আপনি এখন /tmp/script_vars.log এ আপনার স্ক্রিপ্টের ভেরিয়েবলগুলি পুনরুদ্ধার করতে পারেন। বা তার ভিত্তিতে অন্তত কিছু!


0

পার্টিতে কিছুটা দেরি হলেও এখানে আরও একটি পরামর্শ দেওয়া হয়েছে:

#!/bin/bash

set_before=$( set -o posix; set | sed -e '/^_=*/d' )

# create/set some variables
VARIABLE1=a
VARIABLE2=b
VARIABLE3=c

set_after=$( set -o posix; unset set_before; set | sed -e '/^_=/d' )
diff  <(echo "$set_before") <(echo "$set_after") | sed -e 's/^> //' -e '/^[[:digit:]].*/d'

পরিবর্তন + + sed পাইপলাইন কমান্ড লাইন পছন্দসই বিন্যাসে সব স্ক্রিপ্ট-সংজ্ঞায়িত ভেরিয়েবল (ওপি এর পোস্ট উল্লেখিত হিসাবে) আউটপুট:

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