ব্যাশে কীভাবে কেবল সংজ্ঞায়িত ভেরিয়েবল (শেল এবং / অথবা পরিবেশের ভেরিয়েবল) মুদ্রণ করা যায়


57

বাশ বিল্টিন কমান্ড set, যদি তর্ক ছাড়াই আহ্বান করা হয় তবে সমস্ত শেল এবং এনভায়রনমেন্ট ভেরিয়েবল প্রিন্ট করবে তবে সমস্ত নির্ধারিত ফাংশনও প্রিন্ট করবে এটি আউটপুটটিকে মানুষের পক্ষে অব্যবহারযোগ্য এবং কঠিন করে তোলে grep

আমি কীভাবে ব্যাশ বিল্টিন কমান্ডটি setকেবল ভেরিয়েবলগুলি মুদ্রণ করতে পারি এবং কার্যগুলি না?

অন্যান্য শৃঙ্খলাগুলি রয়েছে যা কেবল শেল ভেরিয়েবলগুলিই ফাংশন ব্যতীত মুদ্রণ করে?

দ্রষ্টব্য: বাশ শেল ভেরিয়েবল এবং পরিবেশের ভেরিয়েবলের মধ্যে পার্থক্য করে differen এখানে দেখুন পরিবেশে পরিবর্তনশীল এবং রফতানি হওয়া পরিবেশের ভেরিয়েবলের মধ্যে পার্থক্য

উত্তর:


51

"অন্য কোনও কমান্ড রয়েছে যা কেবলমাত্র শেল ভেরিয়েবলগুলি ফাংশন ব্যতীত মুদ্রণ করে?"

ম্যান ব্যাশে, বিভাগে শিল বুটিন কম্যান্ডস (সেট বিভাগে) এ বলে: "পসিক্স মোডে কেবল শেল ভেরিয়েবল তালিকাভুক্ত করা হয়।"

(set -o posix; set)

দ্রষ্টব্য: ()বাক্য গঠনটি একটি সাব-শেল তৈরি করে, যদি আপনি কাঁটাচামড়া পছন্দ না করেন তবে আরও ভার্বোজ সংস্করণ ব্যবহার করুন

set -o posix; set; set +o posix

1
এখন পর্যন্ত সর্বোত্তম সমাধান
রুস্লান

1
সাধারণত আনট্রিস্টিং ভেরিয়েবলগুলির একটি গুচ্ছ শুরু হয় _যা থেকে সহজেই মুক্তি পাওয়া যায়:(set -o posix ; set | grep -v ^_)
হাইড

এতোদিন আমাকেও বিরক্ত করছে! _ দিয়ে শুরু হওয়া লাইনগুলি গ্রিপিং করা আপনার কাছে যদি বহু-লাইন মান থাকে তবে এটি যথেষ্ট পরিমাণে কার্যকর হয় না, তবে এটি কৌশলে মানের বিষয়বস্তু ছেড়ে যাবে। যেহেতু সেটগুলি লাইনগুলি যথাযথভাবে মুদ্রণ করে, সমস্ত লাইন শেষ হবে, তাই আপনি প্রথম _ লাইনের পরে ফলাফলগুলি কেবল কাটাতে পারেন, এটি ব্যবহার করে:set -o posix; set | sed -e '/^_/,$d'; set +o posix;
স্কট

1
কেবল একটি নোট: বন্ধনীগুলি গুরুত্বপূর্ণ (set -o posix; set)। বন্ধনী ব্যতীত বর্তমান বাশ শেলের আচরণটি পিক্সিক মানের সাথে মেলে। (ডান্নো এর অর্থ কী তবে গুরুত্বপূর্ণ মনে হচ্ছে)) বন্ধনীগুলি সহ, বসটি অপরিবর্তিত রয়েছে।
জন রেড

1
পার্শ্ব প্রতিক্রিয়া : সেট POSIXLY_CORRECT=yএবং যুক্ত posixকরে$SHELLOPTS
টম হেল

31

এখানে কিছু কর্মক্ষেত্র রয়েছে:

$ comm -3 <(declare | sort) <(declare -f | sort)

ভাঙ্গন:

  1. declare প্রতিটি সংজ্ঞায়িত ভেরিয়েবল (রফতানি হওয়া বা না) প্রিন্ট করে এবং ফাংশন।
  2. declare -f মুদ্রণ শুধুমাত্র ফাংশন।
  3. comm -3উভয়ের জন্য সাধারণ সমস্ত লাইন সরিয়ে ফেলবে। কার্যত এটি কেবল ভেরিয়েবলগুলি রেখে ফাংশনগুলি সরিয়ে ফেলবে।

রফতানি করা হয় না শুধুমাত্র ভেরিয়েবল মুদ্রণের জন্য:

$ comm -3 <(comm -3 <(declare | sort) <(declare -f | sort)) <(env | sort)

আরেকটি কাজ

$ declare -p

এটি কেবল ভেরিয়েবলগুলি মুদ্রণ করবে তবে কিছু কুৎসিত বৈশিষ্ট্য সহ।

declare -- BASH="/bin/bash"
declare -ir BASHPID=""
declare -A BASH_ALIASES='()'
declare -a BASH_ARGC='()'
...

আপনি ... কাটা ব্যবহার করে বৈশিষ্ট্যগুলি কেটে ফেলতে পারেন

$ declare -p | cut -d " " -f 3

একটি খারাপ দিক হ'ল আইএফএসের মান প্রদর্শিত হওয়ার পরিবর্তে ব্যাখ্যা করা হয়।

তুলনা করা:

$ comm -3 <(declare | sort) <(declare -f | sort)
...
IFS=$' \t\n'
...
$ declare -p | cut -d " " -f 3
...
IFS="
"
...

"এক লাইনে থাকা একাকী হওয়ার কারণে এটি আরও প্রক্রিয়াকরণের জন্য আউটপুটটি ব্যবহার করা বেশ শক্ত করে তোলে । এটি রোধ করার জন্য সম্ভবত কিছু আইএফএস-ফু করা যেতে পারে।


তবুও আরেকটি কাজ, ব্যবহার করে compgen:

$ compgen -v

ব্যাশ বিল্টিন compgenসম্পূর্ণরূপে স্ক্রিপ্টগুলিতে ব্যবহার করা হত। এই লক্ষ্যে, compgen -vসমস্ত সংজ্ঞায়িত ভেরিয়েবল তালিকাভুক্ত করে। অবক্ষয়: এটি কেবলমাত্র পরিবর্তনশীল নাম তালিকাভুক্ত করে, মানগুলি নয়।

মানগুলিও তালিকাভুক্ত করার জন্য এখানে একটি হ্যাক।

$ compgen -v | while read var; do printf "%s=%q\n" "$var" "${!var}"; done

সুবিধা: এটি একটি খাঁটি বাশ সমাধান। অসুবিধা: কিছু মূল্যবোধ বিভ্রান্ত হয় কারণ ব্যাখ্যাটির মাধ্যমে printf। এছাড়াও পাইপ এবং / অথবা লুপ থেকে সাবশেল কিছু অতিরিক্ত ভেরিয়েবল যুক্ত করে।


কোনও declare ...| cutভেরিয়েবলের জন্য কোনও বৈশিষ্ট্য না থাকলে কী আপনার পাইপটি ভেঙে যায়? আমি অনুমান করছি যে --এটি ক্ষেত্রে ব্যবহৃত হয়, তবে আমি এখনও অস্বস্তিতে রয়েছি। sedনিরাপদ হতে পারে, অর্থাত্declare -p | sed 's/^.* \([^ ]\+\)$/\1/'
জেএমডিটি

+1 এর জন্য compgen:)
আরএসফালকন

13

typesetBuiltin অদ্ভুত শুধুমাত্র (ফাংশন দেখানোর জন্য একটি বিকল্প থাকে -f) কিন্তু না শুধুমাত্র পরামিতি দেখানোর জন্য। ভাগ্যক্রমে, typeset(বা set) সমস্ত ফাংশন, ফাংশন এবং প্যারামিটারের নামগুলিতে নিউলাইন বা সমান চিহ্ন থাকতে পারে না এবং পরামিতি মানগুলিতে নিউলাইনগুলি উদ্ধৃত করা হয় (তারা উপস্থিত হয় \n) এর আগে সমস্ত পরামিতি প্রদর্শন করে । সুতরাং আপনি প্রথম লাইনে থামতে পারেন যাতে সমান চিহ্ন নেই:

set | awk -F '=' '! /^[0-9A-Z_a-z]+=/ {exit} {print $1}'

এটি কেবলমাত্র প্যারামিটারের নামগুলি মুদ্রণ করে; আপনি যদি মানগুলি চান তবে এটিতে পরিবর্তন print $1করুন print $0

নোট করুন যে এটি সমস্ত প্যারামিটারের নাম মুদ্রণ করে (প্যারামিটার এবং ভেরিয়েবলগুলি এখানে প্রতিশব্দ হিসাবে ব্যবহৃত হয়), কেবল পরিবেশের ভেরিয়েবলগুলি নয় ("পরিবেশগত পরিবর্তনশীল" "রফতানি প্যারামিটারগুলির প্রতিশব্দ)")

আরও মনে রাখবেন যে এটি অনুমান করে যে কোনও নামের সাথে পরিবেশের পরিবর্তনশীল নেই যা প্যারামিটার নামের সাথে বাশের বাধাগুলির সাথে মেলে না। এই জাতীয় পরিবর্তনগুলি বাশের ভিতরে তৈরি করা যায় না তবে বাশ শুরু হওয়ার সাথে সাথে পরিবেশ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হতে পারে:

env 'foo ()
{
  =oops' bash

দুর্দান্ত সমাধান! আমি এমনকি প্রথম লাইনে '=' নেই কেবল থামার কথা ভাবিনি। +1
স্টিভেন ডি

সমানভাবে, সেড সহ: set | sed '/=/!Q'
টবি স্পিড

7

আমি নিশ্চিত না যে কেউ কীভাবে setকেবল ভেরিয়েবল প্রিন্ট করতে পারে । তবে এর আউটপুটটি দেখে set, আমি নিম্নলিখিতগুলি নিয়ে আসতে সক্ষম হয়েছি যা কেবলমাত্র ভেরিয়েবলগুলি ধরে ফেলবে বলে মনে হচ্ছে:

$ set | grep "^\([[:alnum:]]\|[[:punct:]]\)\+=" 

মূলত, আমি লাইনগুলি খুঁজছি যা অক্ষর, সংখ্যা বা বিরামচিহ্ন দিয়ে শুরু হয় যার পরে "=" হয়। যে আউটপুট আমি দেখেছি তা থেকে, এটি সমস্ত ভেরিয়েবলকে ধরে ফেলে; তবে আমি সন্দেহ করি যে এটি খুব বহনযোগ্য।

যদি, আপনার শিরোনাম অনুসারে, আপনি এই তালিকা থেকে রফতানি করা ভেরিয়েবলগুলি তালিকা থেকে বিয়োগ করতে চান এবং এইভাবে রফতানিহীন ভেরিয়েবলগুলির একটি তালিকা পেতে চান, তবে আপনি এর মতো কিছু করতে পারেন

$ set | grep "^\([[:alnum:]]\|[[:punct:]]\)\+=" | sort > ./setvars && env | sort | comm -23 ./setvars - 

এটিকে কিছুটা ভাঙতে, এটি যা করে তা এখানে:

  1. set | grep "^\([[:alnum:]]\|[[:punct:]]\)\+=" | sort > ./setvars : এটি আশাকরির সাথে সমস্ত পরিবর্তনশীল (যেমন আগে আলোচনা হয়েছে) পেয়ে যায়, সেগুলি সাজায়, এবং ফলটিকে একটি ফাইলের মধ্যে আটকে দেয়।
  2. && env | sort: পূর্ববর্তী কমান্ডটি সম্পূর্ণ হওয়ার পরে, আমরা কল করব envএবং এর আউটপুটটি বাছাই করব।
  3. | comm -23 ./setvars -: পরিশেষে, আমরা পাইপের সাজানো আউটপুট envমধ্যে commএবং ব্যবহার -23বিকল্প লাইন সেট থেকে আমাদের আউটপুট অনন্য এই ক্ষেত্রে, লাইন যে প্রথম যুক্তি অনন্য প্রিন্ট করতে।

আপনি যখন কাজটি শেষ করেন আপনি কমান্ডটি দিয়ে তৈরি টেম্প ফাইলটিকে ক্লিনআপ করতে চাইতে পারেন rm ./setvars


আপনার কমান্ডের সমস্যাটি বহনযোগ্যতা নয় (অবশ্যই এটি ব্যাশের জন্য নির্দিষ্ট, তবে গ্রেপ সাইডে কোনও সমস্যা নেই)। সমস্যাটি হ'ল আপনি ফাংশন সংজ্ঞায় কিছু লাইন ধরেছেন। বাশ বেশিরভাগ ফাংশন কোডকে সন্নিবেশ করায়, তবে এটি সমস্ত নয়, বিশেষত এখানে নথির ভিতরে পাঠ্য নয় ( f () {|cat <<EOF|foo=bar|EOF|}যেখানে |একটি লাইন বিরতি উপস্থাপন করা হয়)।
গিলস 'অশুভ হওয়া বন্ধ করুন' ২:01

6

কমান্ডটি ব্যবহার করুন env। এটি ফাংশন মুদ্রণ করে না।


1
এটি কোনও স্ক্রিপ্টের অভ্যন্তরে ব্যবহৃত হলে তা করে।
ডকসালভাইজার

2

কমান্ড প্রিন্টেনভ চেষ্টা করুন:

$printenv

6
প্রিন্টেনভ এবং এনএনভি কেবল এক্সপোর্ট রফতানি (পরিবেশ) ভেরিয়েবল এবং অ-এক্সপোর্ট (শেল) ভেরিয়েবলগুলি নয়।
ল্রি

@ লরি ধন্যবাদ! আমি ভাবলাম কীভাবে কীভাবে রফতানি ভেরিয়েবলগুলি মুদ্রণ করা যায়।
মার্ক স্টুয়ার্ট

1

ব্যাশে, এটি কেবল পরিবর্তনশীল নামগুলি মুদ্রণ করবে:

compgen -v

অথবা, যদি মানগুলিরও প্রয়োজন হয়, ব্যবহার করুন:

declare -p

আপনার প্রচেষ্টার জন্য আপনাকে ধন্যবাদ. দয়া করে নোট করুন আমি ইতিমধ্যে আমার উত্তর যে সম্ভাবনা উল্লেখ করেছি unix.stackexchange.com/a/5691/1170 একটি ভোট দিন যাহাই হউক না কেন আছে।
লেসমানা

0

আরসি স্ক্রিপ্ট থেকে ওয়ারগুলি বাদ পড়েছে তা নিশ্চিত করার জন্য একটি পরিষ্কার শেলের বিচ্ছিন্নতা

## get mostly local vars
diff_env(){
    diff <(bash -cl 'set -o posix && set') \
        <(set -o posix && set && set +o posix) | \
        grep -E "^>|^\+" | \
        grep -Ev "^(>|\+|\+\+) ?(BASH|COLUMNS|LINES|HIST|PPID|SHLVL|PS(1|2)|SHELL|FUNC)" | \
        sed -r 's/^> ?|^\+ ?//'
}

সংস্করণটি commখুব সংশ্লেষিত হবে


0

গৃহীত উত্তরটি দুর্দান্ত। আমি এমন একটি বিকল্প প্রস্তাব দিচ্ছি যাতে পসিক্স মোড সেট করা জড়িত না:

ফাংশন স্থিতি কোনও ফাইলে সংরক্ষণ করার জন্য যে কৌশলটি ব্যবহার করছি তা এখানে রয়েছে যাতে আমি এটি পরে চালিয়ে যেতে পারি। প্রথমটি একটি রাষ্ট্রীয় ডাম্প উত্পাদন করে এবং দ্বিতীয়টি পরিবর্তনশীল নামের মাত্র একটি তালিকা তৈরি করে।

set 2>/dev/null | while read a; do [[ $a == *=* ]] || break; echo $a; done 

set 2>/dev/null | while read a; do [[ $a == *=* ]] || break; echo ${a/=*}; done 

উভয়ই লাইন ডাম্পিং করে কাজ করে যতক্ষণ না এটি '=' চর ছাড়া একটি খুঁজে পায়, যা প্রথম ফাংশন তালিকাভুক্ত হওয়ার পরে ঘটে। পরেরটি অ্যাসাইনমেন্ট বন্ধ করে দেয়।

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