একটি মেকফিল ভেরিয়েবলকে কমান্ডের আউটপুট কীভাবে নির্ধারণ করা যায়


224

আমার শর্তসাপেক্ষে কিছু তৈরি করার নিয়ম সম্পাদন করা দরকার, কেবলমাত্র পাইথন ইনস্টল করা যদি একটি নির্দিষ্ট সংস্করণের চেয়ে বড় হয় (2.5 বলুন)।

আমি ভেবেছিলাম মৃত্যুদন্ড কার্যকর করার মতো কিছু করতে পারি:

python -c 'import sys; print int(sys.version_info >= (2,5))'

এবং তারপরে একটি ifeqবিবৃতিতে আউটপুট ('1' ঠিক আছে তবে '0') ব্যবহার করুন

একটি সাধারণ বাশ শেল স্ক্রিপ্টে এটি ঠিক:

MY_VAR=`python -c 'import sys; print int(sys.version_info >= (2,5))'`

তবে এটি কোনও মেকফাইলে কাজ করে না।

কোনও পরামর্শ? এটি অর্জনের জন্য আমি অন্য যে কোনও বুদ্ধিমান কাজ করতে পারি না।


কমান্ডটির চারপাশে অদ্ভুত ব্যাক টিক্স একটি মেকফিলে আমার জন্য অন্যান্য স্ক্রিপ্টগুলি কার্যকর করার জন্য কাজ করে। অন্য কিছু হতে পারে।
লিফ গ্রুয়েনউল্ড

উত্তর:


345

মেক shellবিল্টইনকে পছন্দ করুন UseMY_VAR=$(shell echo whatever)

me@Zack:~$make
MY_VAR IS whatever

me@Zack:~$ cat Makefile 
MY_VAR := $(shell echo whatever)

all:
    @echo MY_VAR IS $(MY_VAR)

34
শেল একটি স্ট্যান্ডার্ড মেক বিল্টিন কমান্ড নয়। এটি একটি জিএনইউ মেক বিল্টিন।
ডেরিকসন

12
stackoverflow.com/a/2373111/12916 পালানোর বিষয়ে একটি গুরুত্বপূর্ণ নোট যুক্ত করে $
জেসি গ্লিক

6
এই সহজ উদাহরণ কাজ করে। এটি শেল কমান্ড পাইপলাইনেও কাজ করে। কিন্তু এটা অপরিহার্য যে আপনি ব্যবহার করা উচিত $$ শেল কমান্ড মধ্যে $ প্রতিনিধিত্ব করতে
সের্গেই পি ওরফে আকাশী নীল

28
প্রশ্নটি হালকা পুরানো হওয়ার পরে, MY_VAR: = $ (শেল ...) করা ভাল, অন্যথায় যতবারই MY_VAR মূল্যায়ন করা হয়, এটি আবার $ (শেল ...) চালায়।
রাশ শুল্টজ

আমার শেল এবং খোলার প্রথম বন্ধনীগুলির মধ্যে একটি জায়গা ছিল এবং কেবল স্থানটি সরিয়ে দেওয়ার পরে আমার মেকফিল আউটপুট পাঠ্যটি পেরেছিল
পিটারচৌলা

29

অ্যাসাইনমেন্টটি মোড়ানো evalআমার পক্ষে কাজ করছে।

# dependency on .PHONY prevents Make from 
# thinking there's `nothing to be done`
set_opts: .PHONY
  $(eval DOCKER_OPTS = -v $(shell mktemp -d -p /scratch):/output)

6
"দ্রষ্টব্য: এখানে ক্লিক করা কিছু নেই এমন চিন্তাভাবনা থেকে বাধা দেয়" " উম, যে কি .PHONY always make these targetsজন্য হয়।
আন্ডারস্কোর_আডি

ধন্যবাদ! এটি আমাকে মেকফাইলে "অদ্ভুত বাশ" বাইপাস করতে সহায়তা করে
নাম জি ভিইউ

19

পাইপিং এবং ভেরিয়েবল অ্যাসাইনমেন্টের ভিতরে রেসিপিটির সাথে আরও জটিল উদাহরণ এখানে দেওয়া হয়েছে:

getpodname:
    # Getting pod name
    @eval $$(minikube docker-env) ;\
    $(eval PODNAME=$(shell sh -c "kubectl get pods | grep profile-posts-api | grep Running" | awk '{print $$1}'))
    echo $(PODNAME)

2
যদি এটি কখনও কাজে আসে তবে আমি PODNAMEমোতায়েনের নামটি পেতে কিছুটা অনুরূপ পন্থা ব্যবহার করছি :$(eval PODNAME=$(shell sh -c "kubectl get pod -l app=sqlproxy -o jsonpath='{.items[0].metadata.name}'"))
জান রিখর

সিনট্যাক্স আমাকে এক সেকেন্ডের জন্য বিভ্রান্ত করেছিল যতক্ষণ না বুঝেছি আপনি শেল বিল্টিন ইভাল (ডকার-এনভির লাইনে) এবং মেক ফাংশন ইভাল (পরের লাইনে) উভয়ই ব্যবহার করছেন ।
ব্রায়ান গর্ডন

17

সমস্যার সমাধান করে এমন প্রকৃত সিনট্যাক্সের দৃশ্যমানতা বাড়াতে আমি একটি উত্তর লিখছি। দুর্ভাগ্যক্রমে, কেউ যেটাকে তুচ্ছ হিসাবে দেখতে পাবে তা যুক্তিসঙ্গত প্রশ্নের সহজ উত্তর খুঁজছেন এমন ব্যক্তির পক্ষে খুব তাৎপর্যযুক্ত মাথাব্যথা হয়ে উঠতে পারে।

নিম্নলিখিত "Makefile" ফাইলের মধ্যে রাখুন।

MY_VAR := $(shell python -c 'import sys; print int(sys.version_info >= (2,5))')

all:
    @echo MY_VAR IS $(MY_VAR)

আপনি যে আচরণটি দেখতে চান তা নীচে রয়েছে (ধরে নিই যে আপনি সাম্প্রতিক অজগরটি ইনস্টল করেছেন)।

make
MY_VAR IS 1

আপনি যদি উপরের পাঠ্যটিকে মেকফাইলে অনুলিপি করে আটকান, আপনি কি এটি পাবেন? সম্ভবত না. আপনি এখানে রিপোর্ট করা মত একটি ত্রুটি সম্ভবত পাবেন:

মেকফাইল: 4: *** নিখোঁজ বিভাজক। স্টপ

কেন: কারণ যদিও আমি ব্যক্তিগতভাবে একটি খাঁটি ট্যাব ব্যবহার করেছি, স্ট্যাক ওভারফ্লো (সহায়ক হওয়ার চেষ্টা) আমার ট্যাবটিকে অনেকগুলি ফাঁকে রূপান্তর করে। হতাশ ইন্টারনেট নাগরিক আপনি এখন এটি অনুলিপি করুন এই ভেবে যে আপনার কাছে এখন আমি ব্যবহার করেছি একই পাঠ্য। মেক কমান্ড, এখন স্পেসগুলি পড়ে এবং দেখতে পাবে যে "সমস্ত" কমান্ডটি ভুলভাবে ফর্ম্যাট হয়েছে। সুতরাং উপরের পাঠ্যটি অনুলিপি করুন, এটি আটকান এবং তারপরে "@echo" এর আগে সাদা স্পেসটি কোনও ট্যাবে রূপান্তর করুন এবং এই উদাহরণটি শেষ পর্যন্ত আশাবাদী আপনার জন্য কাজ করা উচিত।


আপনি কোন সম্পাদকে আটকান তা নির্ভর করে। আমি স্রেফ একটি অনির্দিষ্ট মেকফিল সম্পাদক সম্পাদনা করে অনুলিপি করে আটকালাম, এবং একটি শীর্ষস্থানীয় ট্যাব পেয়েছি (প্রয়োজনীয় হিসাবে)।
টেকনোফিল

ওহ আমি এটা ভাবিনি। পরমাণু এখানে।
অ্যালানএসই

11

এই জাতীয় রেসিপি সম্পর্কে সাবধান

target:
    MY_ID=$(GENERATE_ID);
    echo $MY_ID;

এটি দুটি জিনিস ভুল করে। রেসিপিটির প্রথম লাইনটি দ্বিতীয় লাইন থেকে পৃথক শেল ইভেন্টে কার্যকর করা হয়। এর মধ্যে ভেরিয়েবলটি হারিয়ে যায়। দ্বিতীয় জিনিসটি ভুলটি হল যে $পালানো হয়নি।

target:
    MY_ID=$(GENERATE_ID); \
    echo $$MY_ID;

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

আমি বুঝতে পারি যে আসল পোস্টটি কীভাবে শেল কমান্ডের ফলাফলকে একটি মেক ভেরিয়েবলের মধ্যে পাবেন এবং এই উত্তরটি কীভাবে এটি শেল ভেরিয়েবলে পাবেন তা দেখায় realize তবে অন্যান্য পাঠকরা উপকৃত হতে পারেন।

একটি চূড়ান্ত উন্নতি, যদি গ্রাহক কোনও "পরিবেশের পরিবর্তনশীল" সেট করার প্রত্যাশা করেন, তবে আপনাকে এটি রফতানি করতে হবে।

my_shell_script
    echo $MY_ID

Makefile এ প্রয়োজন হবে

target:
    export MY_ID=$(GENERATE_ID); \
    ./my_shell_script;

আশা করি যে কাউকে সাহায্য করবে। সাধারণভাবে রেসিপিগুলির বাইরে কোনও আসল কাজ করা এড়ানো উচিত, কারণ কেউ যদি '--dry-run' বিকল্পের সাহায্যে মেকফিল ব্যবহার করে তবে এটি কী করবে তা কেবল দেখার জন্য এটির কোনও অনাকাঙ্ক্ষিত পার্শ্ব প্রতিক্রিয়া হবে না। প্রতিটি $(shell)কল সংকলন সময়ে মূল্যায়ন করা হয় এবং কিছু বাস্তব কাজ ঘটনাক্রমে করা যেতে পারে। যখন সম্ভব হয় তখন আসল কাজটি, আইডি উত্পন্ন করার মতো, রেসিপিগুলির অভ্যন্তরে রেখে দেওয়া ভাল।


9

জিএনইউ মেকের সাহায্যে আপনি স্বেচ্ছাসেবক কমান্ড লাইন অনুরোধগুলি থেকে আউটপুট সংরক্ষণ shellএবং পরিচালনা evalকরতে এবং চালাতে পারেন । নীচের উদাহরণ এবং যা ব্যবহার করে তাদের মধ্যে পার্থক্য :=হ'ল :=অ্যাসাইনমেন্টটি একবার হয় (যখন এটির মুখোমুখি হয়) এবং সবার জন্য। এর সাথে পুনরাবৃত্তভাবে প্রসারিত ভেরিয়েবলগুলি =আরও কিছুটা "অলস" হয়; ভেরিয়েবলটি উল্লেখযোগ্য না হওয়া পর্যন্ত অন্যান্য ভেরিয়েবলের রেফারেন্স থেকে যায় এবং পরবর্তী সময়ে প্রতিটি পরিবর্তনশীল উল্লেখ করা হয় , যা "ধারাবাহিক, কলযোগ্য, স্নিপেটস" তৈরির জন্য প্রয়োজনীয়। আরও তথ্যের জন্য ভেরিয়েবল সেট করার ম্যানুয়ালটি দেখুন ।

# Generate a random number.
# This is not run initially.
GENERATE_ID = $(shell od -vAn -N2 -tu2 < /dev/urandom)

# Generate a random number, and assign it to MY_ID
# This is not run initially.
SET_ID = $(eval MY_ID=$(GENERATE_ID))

# You can use .PHONY to tell make that we aren't building a target output file
.PHONY: mytarget
mytarget:
# This is empty when we begin
    @echo $(MY_ID)
# This recursively expands SET_ID, which calls the shell command and sets MY_ID
    $(SET_ID)
# This will now be a random number
    @echo $(MY_ID)
# Recursively expand SET_ID again, which calls the shell command (again) and sets MY_ID (again)
    $(SET_ID)
# This will now be a different random number
    @echo $(MY_ID)

আপনার প্রতি প্রথম সুন্দর ব্যাখ্যাটি আমি পেয়েছি every ধন্যবাদ. যদিও একটি বিষয় যোগ করতে হবে তা হ'ল যদি এমন $(SET_ID)একটি ifধারাটির মধ্যে থাকে যা মিথ্যা হয় তবে এটি এখনও বলা হয়
রোমান

এটি এখনও বলা হয় কারণ যদি স্টেম্টগুলি মেকফাইল সংকলন সময়ে রান-টাইমে নয় তবে মূল্যায়ন করা হয়। রান-টাইম নির্দিষ্ট নির্দেশাবলীর জন্য সেগুলি রেসিপিগুলিতে রাখুন। যদি তারা শর্তযুক্ত হয় তবে রেসিপির অংশ হিসাবে স্ট্যাম্টস, ব্যাশ / শেলের মধ্যে লেখা থাকলে যোগ করুন।
জুরাজ 5'19

0

নীচের উদাহরণে, আমি মেকফিল ফোল্ডার পাথ সংরক্ষণ করেছি LOCAL_PKG_DIRএবং তারপরে LOCAL_PKG_DIRলক্ষ্যগুলিতে পরিবর্তনশীল ব্যবহার করব ।

Makefile নামক:

LOCAL_PKG_DIR := $(shell eval pwd)

.PHONY: print
print:
    @echo $(LOCAL_PKG_DIR)

টার্মিনাল আউটপুট:

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