আমি কেন একটি পরিবেশের পরিবর্তনশীল নির্দিষ্ট করতে এবং একই কমান্ড লাইনে এটি প্রতিধ্বন করতে পারি না?


91

এই স্নিপেট বিবেচনা করুন:

$ SOMEVAR=AAA
$ echo zzz $SOMEVAR zzz
zzz AAA zzz

এখানে আমি সেট করেছি $SOMEVARকরার AAAপ্রথম লাইনে - এবং যখন আমি দ্বিতীয় লাইন তে এটি echo, আমি পেতে AAAবিষয়বস্তু হিসাবে প্রত্যাশিত।

তবে তারপরে, যদি আমি একই কমান্ড লাইনে ভেরিয়েবলটি নির্দিষ্ট করার চেষ্টা করি echo:

$ SOMEVAR=BBB echo zzz $SOMEVAR zzz
zzz AAA zzz

... আমি BBBযেমনটি প্রত্যাশা করেছিলাম তেমনটি পাই না - আমি পুরানো মান ( AAA) পাই ।

জিনিস কি এইভাবেই অনুমান করা যায়? যদি তাই হয় তবে কীভাবে আসবেন আপনি এর মতো ভেরিয়েবল নির্দিষ্ট করতে পারবেন LD_PRELOAD=/... program args ...এবং এটির কাজ রয়েছে? আমি কী মিস করছি?


4
আপনি কাজটি একটি পৃথক বিবৃতি তৈরি করার সময়, বা কোনও স্ক্রিপ্টকে তার নিজস্ব পরিবেশের সাথে ডাকার সময় কার্যকর হয় তবে বর্তমান পরিবেশে কোনও কমান্ড প্রিফেস করার সময় নয়। মজাদার!
টড এ জ্যাকবস

4
কারণ LD_PRELOADয়ে সব অলৌকিক কাজ পরিবর্তনশীল প্রোগ্রামের মধ্যে সেট করা হয় পরিবেশ - না তার কমান্ড লাইন।
পরবর্তী বিজ্ঞপ্তি না দেওয়া পর্যন্ত বিরতি দেওয়া হয়েছে।

উত্তর:


103

আপনি যা দেখেন তা হ'ল প্রত্যাশিত আচরণ। সমস্যাটি হ'ল প্যারেন্ট শেলটি $SOMEVARপরিবর্তিত পরিবেশের সাথে কমান্ডের আগে কমান্ড লাইনে মূল্যায়ন করে। $SOMEVARআপনার পরিবেশ নির্ধারণের আগ পর্যন্ত আপনার পিছিয়ে দেওয়া মূল্যায়ন হওয়া দরকার।

আপনার তাত্ক্ষণিক বিকল্পগুলির মধ্যে রয়েছে:

  1. SOMEVAR=BBB eval echo zzz '$SOMEVAR' zzz
  2. SOMEVAR=BBB sh -c 'echo zzz $SOMEVAR zzz'

এই উভয়ই প্যারেন্ট শেলটিকে মূল্যায়ন থেকে বিরত রাখতে একক উদ্ধৃতি ব্যবহার করে $SOMEVAR; এটি পরিবেশে সেট করার পরে কেবলমাত্র মূল্যায়ন করা হয় (অস্থায়ীভাবে, একক আদেশের সময়কালের জন্য)।

আরেকটি বিকল্প হ'ল সাব-শেল নোটেশনটি ব্যবহার করা (যেমনটি তার উত্তরে মার্কাস কুহানও পরামর্শ করেছিলেন ):

(SOMEVAR=BBB; echo zzz $SOMEVAR zzz)

ভেরিয়েবলটি কেবলমাত্র সাব-শেলটিতে সেট করা আছে


দুর্দান্ত, @ জোনাথনলফলার - ব্যাখ্যাটির জন্য অনেক ধন্যবাদ; চিয়ার্স!
sdaau

@ মার্কাস-কুহন থেকে সংযোজন করা অত্যধিক পর্যালোচনা করা কঠিন।
অ্যালেক্স চে

37

সমস্যা, পুনরায় দেখা

বেশ স্পষ্টভাবে, ম্যানুয়ালটি এই বিষয়টিতে বিভ্রান্ত করছে। গনুহ ব্যাশ ম্যানুয়াল বলেছেন:

শেল পরামিতিগুলিতে বর্ণিত কোনও সাধারণ কমান্ড বা ফাংশনের পরিবেশ [নোট করুন যে এটি বিল্টিনগুলি বাদ দেয়] সাময়িকভাবে প্যারামিটার অ্যাসাইনমেন্ট সহ এটি উপস্থাপনের মাধ্যমে বাড়ানো যেতে পারে। এই অ্যাসাইনমেন্ট বিবৃতিগুলি কেবল সেই আদেশ দ্বারা প্রদর্শিত পরিবেশকে প্রভাবিত করে।

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

$ TESTVAR=bbb env | fgrep TESTVAR
TESTVAR=bbb

কারণ এনভিনিউ কমান্ডের জন্য পরিবেশটি কার্যকর করার আগে এটি পরিবর্তন করা হয়েছিল। তবে এটি কাজ করবে না:

$ set -x; TESTVAR=bbb echo aaa $TESTVAR ccc
+ TESTVAR=bbb
+ echo aaa ccc
aaa ccc

কারণ যখন শেল দ্বারা পরামিতি প্রসারিত হয়।

দোভাষী পদক্ষেপ

সমস্যার আরেকটি অংশ হ'ল বাশ তার দোভাষীর জন্য এই পদক্ষেপগুলি সংজ্ঞায়িত করে :

  1. কোনও ফাইল (শেল স্ক্রিপ্টস দেখুন) থেকে ইনপুট পড়বে, -c ইনভোকেশন বিকল্পের জন্য আর্গুমেন্ট হিসাবে সরবরাহ করা স্ট্রিং থেকে (দাওয়াত দাওয়াত দেখুন) বা ব্যবহারকারীর টার্মিনাল থেকে input
  2. উদ্ধৃতিতে বর্ণিত উদ্ধৃতি বিধি মেনে শব্দ এবং অপারেটরগুলিতে ইনপুটটি ভেঙে দেয়। এই টোকেনগুলি মেটাচার্যাক্টর দ্বারা পৃথক করা হয়। এলিয়াস সম্প্রসারণ এই পদক্ষেপ দ্বারা সম্পাদিত হয় (উপাধি দেখুন)।
  3. টোকেনগুলি সাধারণ এবং যৌগিক কমান্ডগুলিতে পার্স করে (শেল কমান্ডগুলি দেখুন)।
  4. বিভিন্ন শেল বিস্তৃতি (শেল প্রসার দেখুন) সম্পাদন করে, প্রসারিত টোকেনগুলি ফাইলের তালিকায় (ফাইলের নাম সম্প্রসারণ দেখুন) এবং আদেশ এবং আর্গুমেন্টগুলি ভেঙে দেয়।
  5. কোনও প্রয়োজনীয় পুনর্নির্দেশগুলি সম্পাদন করে (পুনর্নির্দেশগুলি দেখুন) এবং যুক্তি তালিকা থেকে পুনঃনির্দেশ অপারেটর এবং তাদের অপারেশনগুলি সরিয়ে দেয়।
  6. কমান্ড কার্যকর করে (দেখুন আদেশগুলি কার্যকর করা)
  7. Commandচ্ছিকভাবে কমান্ডটি সম্পন্ন হওয়ার জন্য অপেক্ষা করে এবং এর প্রস্থান স্থিতি সংগ্রহ করে (প্রস্থান স্থিতি দেখুন)।

এখানে যা ঘটছে তা হ'ল বিল্টিনগুলি তাদের নিজস্ব নির্বাহের পরিবেশটি পায় না, তাই তারা কখনই পরিবর্তিত পরিবেশ দেখতে পায় না। উপরন্তু, সহজ কমান্ড (যেমন / বিন / প্রতিধ্বনি) না একটি পরিবর্তিত ennvironment পেতে (যার কারণে env উদাহরণ চাকরি করতেন) কিন্তু শেল সম্প্রসারণ জায়গা নিচ্ছে বর্তমান পদক্ষেপ # 4 পরিবেশ।

অন্য কথায়, আপনি 'বিনা / প্রতিধ্বনিতে' আআ E টেস্টওয়ার সিসিসি 'পাস করছেন না; আপনি ইন্টারপোলটেড স্ট্রিং (বর্তমান পরিবেশে প্রসারিত) / বিন / প্রতিধ্বনিতে যাচ্ছেন। এই ক্ষেত্রে, যেহেতু বর্তমান পরিবেশের কোনও টেস্টওয়ার নেই , আপনি কেবল কমান্ডটিতে ' সিসিসি' দিয়ে ।

সারসংক্ষেপ

ডকুমেন্টেশন অনেক পরিষ্কার হতে পারে। ভাল জিনিস স্ট্যাক ওভারফ্লো আছে!

আরো দেখুন

http://www.gnu.org/software/bash/manual/bashref.html#Command- এক্সিকিউশন- পরিবেশ


আমি ইতিমধ্যে এটি upvated ছিল - কিন্তু আমি ঠিক এই প্রশ্নে ফিরে এসেছি, এবং এই পোস্টে ঠিক আমার প্রয়োজন পয়েন্টার রয়েছে; অনেক ধন্যবাদ, @ কোডডনোম!
sdaau

আমি ব্যাশ এই এলাকা থেকে এই উত্তর পোস্ট করা হয়েছে পরিবর্তিত হয়েছে জানি না, কিন্তু পূর্বে সমাধান পরিবর্তনশীল বরাদ্দকরণ না এখন builtins সঙ্গে কাজ করে। উদাহরণস্বরূপ, প্রত্যাশিত হিসাবে FOO=foo eval 'echo $FOO'প্রিন্টগুলি foo। এর অর্থ আপনি পছন্দ মতো কাজ করতে পারেন IFS="..." read ...
উইসডেন

আমি মনে করি যা ঘটছে তা হ'ল বাশ আসলে নিজের পরিবেশকে অস্থায়ীভাবে পরিবর্তন করে এবং কমান্ডটি শেষ হওয়ার পরে এটি পুনরুদ্ধার করে, যার অদ্ভুত পার্শ্ব-প্রতিক্রিয়া থাকতে পারে।
ভসডেন

22

আপনি যা চান তা অর্জন করতে, ব্যবহার করুন

( SOMEVAR=BBB; echo zzz $SOMEVAR zzz )

কারণ:

  • আপনাকে অবশ্যই অর্ধেকলন বা নতুন লাইন দ্বারা পরবর্তী কমান্ড থেকে অ্যাসাইনমেন্টটি পৃথক করতে হবে, অন্যথায় পরবর্তী কমান্ডের (প্রতিধ্বনি) জন্য প্যারামিটার সম্প্রসারণের আগে এটি কার্যকর করা হয় না ।

  • আপনাকে বর্তমানের লাইনের বাইরে অস্তিত্ব বজায় রাখছে না তা নিশ্চিত করার জন্য আপনাকে সাব-শেল পরিবেশের মধ্যে অ্যাসাইনমেন্টটি তৈরি করতে হবে।

এই সমাধানটি অন্যের পরামর্শের চেয়ে সংক্ষিপ্ত, নিচু ও দক্ষ এবং বিশেষত এটি একটি নতুন প্রক্রিয়া তৈরি করে না।


4
ভবিষ্যতের গুগল যারা এখানে বেড়াচ্ছেন তাদের জন্য: এটি সম্ভবত এই প্রশ্নের সেরা উত্তর। এটি আরও জটিল করার জন্য, কমান্ডের পরিবেশে আপনার যদি অ্যাসাইনমেন্টের প্রয়োজন হয় তবে আপনাকে এটি রফতানি করতে হবে। সাব-শেল এখনও অ্যাসাইনমেন্টটি ধরে রাখতে বাধা দেয়। (export SOMEVAR=BBB; python -c "from os import getenv; print getenv('SOMEVAR')")
ইজ

@ ইজ আপনার এক উদাহরণ হিসাবে যেমন একটি একক বহিরাগত প্রোগ্রাম কল শেল পরিবর্তনশীল রফতানি করতে, কেবল ব্যবহার করুনSOMEVAR=BBB python -c "from os import getenv; print getenv('SOMEVAR')"
মার্কাস কুহান

10

কারণটি হ'ল এটি এক লাইনের জন্য পরিবেশের পরিবর্তনশীল সেট করে। কিন্তু, echoসম্প্রসারণ করে না , করে না bash। অত: পর, আপনার পরিবর্তনশীল আসলে সম্প্রসারিত আগে কমান্ড এক্সিকিউট করা হয়, যদিও হয় SOME_VARহয় BBBপ্রতিধ্বনি কমান্ড প্রেক্ষাপটে।

প্রভাবটি দেখতে, আপনি এর মতো কিছু করতে পারেন:

$ SOME_VAR=BBB bash -c 'echo $SOME_VAR'
BBB

শিশু প্রক্রিয়া কার্যকর না হওয়া পর্যন্ত এখানে ভেরিয়েবলটি প্রসারিত হবে না, তাই আপনি আপডেট হওয়া মানটি দেখুন। আপনি যদি SOME_VARIABLEপ্যারেন্ট শেলটিতে আবার যাচাই করেন তবে এটি এখনও AAAপ্রত্যাশার মতো।


4
এটি লিখিত হিসাবে কেন কাজ করে না তার সঠিক ব্যাখ্যার জন্য, এবং একটি কার্যক্ষম কাজের জন্য ound
জোনাথন লেফলার

1
SOMEVAR=BBB; echo zzz $SOMEVAR zzz

ব্যবহার করা ; একই লাইনে থাকা বিবৃতি পৃথক করতে।


4
এটি কাজ করে, তবে এটি বেশিরভাগ বিষয় নয়। ধারণাটি হ'ল পরিবেশকে কেবল একটি কমান্ডের জন্য স্থির করে দেওয়া, স্থায়ীভাবে আপনার সমাধানের মতো নয়।
জোনাথন লেফলার

@ কাইরোস এর জন্য ধন্যবাদ; জানি না কী করে এসেছি এতক্ষণে :) আমি কীভাবে ঘুরছিLD_PRELOAD সেমিকোলন ছাড়াই কোনও এক্সিকিউটেবলের সামনে এবং এরকম কাজ করা যায়, যদিও ... আবার অনেক ধন্যবাদ - চিয়ার্স!
sdaau

@ জোনাথন লেফলার - সত্যই এটাই ছিল ধারণা; আমি বুঝতে পারিনি যে সেমিকোলনটি পরিবর্তন স্থায়ী করে দেয় - এটি লক্ষ করার জন্য ধন্যবাদ!
sdaau

1

এখানে একটি বিকল্প রয়েছে:

SOMEVAR=BBB && echo zzz $SOMEVAR zzz

আপনি কমান্ডগুলি ব্যবহার করুন &&বা ;পৃথক করুন, অ্যাসাইনমেন্টটি বহাল থাকবে, যা ওপির পছন্দসই আচরণ নয়। মার্কাস কুহনের এই উত্তরের সঠিক সংস্করণ রয়েছে।
ইজ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.