আমি কীভাবে শর্তাধীন 'সময়' এর মাধ্যমে সাব-শেল পাস করতে পারি?


9

আমার কাছে ভ্যাগ্র্যান্ট বক্সের জন্য একটি সেটআপ স্ক্রিপ্ট রয়েছে যেখানে আমি একক পদক্ষেপগুলি দিয়ে মাপতাম time। এখন আমি শর্তাধীন সময় পরিমাপ সক্ষম বা অক্ষম করতে চাই।

উদাহরণস্বরূপ, আগে একটি লাইন দেখতে হবে:

time (apt-get update > /tmp/last.log 2>&1)

এখন আমি ভেবেছিলাম আমি এই জাতীয় কিছু করতে পারি:

MEASURE_TIME=true
[[ $MEASURE_TIME = true ]] && TIME="time --format=%e" || TIME=""

$TIME (apt-get update > /tmp/last.log 2>&1)

তবে এটি কাজ করবে না:

syntax error near unexpected token `apt-get'
`$TIME (apt-get update > /tmp/last.log 2>&1)'

এখানে সমস্যা কি?


3
ফ্লাক্স ক্যাপাসিটারটি কাজ করার জন্য আপনার কেবলমাত্র লক্ষ্য গতির বেগ প্রয়োজন ;)
স্বর্ণলোকস

2
আপনি কি চুম্বক বলতে চান ? ;)
সিভিএন

উত্তর:


13

সাবসেলের সময় নির্ধারণের জন্য আপনার time কীওয়ার্ডটি দরকার , কমান্ড নয়।

timeভাষার কীওয়ার্ড, ভাষার অংশটি কেবল তখনই স্বীকৃত হয় যখন আক্ষরিকভাবে প্রবেশ করা হয় এবং কমান্ডের প্রথম শব্দ হিসাবে (এবং এর ক্ষেত্রে ksh93, তারপরে পরবর্তী টোকেনটি একটি দিয়ে শুরু হয় না -)। এমনকি প্রবেশ করা "time"একা চলবে না $TIME(এবং timeপরিবর্তে কমান্ডের কল হিসাবে নেওয়া হবে)।

পার্সিংয়ের অন্য রাউন্ড সঞ্চালনের আগে আপনি এখানে এমন এলিয়াস ব্যবহার করতে পারেন যা শেলটি timeকীওয়ার্ডটি সনাক্ত করতে পারে ):

shopt -s expand_aliases
alias time_or_not=
TIMEFORMAT=%E

MEASURE_TIME=true
[[ $MEASURE_TIME = true ]] && alias time_or_not=time

time_or_not (apt-get update > /tmp/last.log 2>&1)

time শব্দ অপশন (ছাড়া লাগবে না -pbash), কিন্তু ফর্ম্যাটের সাথে সেট করা যেতে পারে TIMEFORMATযে পরিবর্তনশীল bash। ( shoptঅংশ হয় bash-specific, অন্যান্য শাঁস সাধারণত যে প্রয়োজন হবে না)।


আপনি বলেছিলেন "সাবসেলের সময় নির্ধারণের জন্য আপনার সময় কীওয়ার্ডের প্রয়োজন"। আমি আশ্চর্য এই আচরণ কিছু নথিভুক্ত যেখানে?
cuonglm

@ কুওগলম, দেখুনinfo -f bash --index-search=time
স্টাফেন চেজেলাস

3

সময় একটি aliasওয়ান ওয়ে এটা করতে, এই করতে সঙ্গে সম্পন্ন করা evalপাশাপাশি - এটা শুধু যে আপনি এত চান না evalহিসাবে আপনি করতে চান কমান্ড সঞ্চালনের evalকমান্ড ঘোষণা

আমি aliasএস পছন্দ করি - আমি সর্বদা তাদের ব্যবহার করি তবে আমি ফাংশনগুলি আরও পছন্দ করি - বিশেষত পরামিতিগুলি হ্যান্ডেল করার দক্ষতা এবং এএসের জন্য প্রয়োজনীয় হিসাবে কমান্ড পজিশনে তাদের প্রসারিত করার প্রয়োজন নেই alias

সুতরাং আমি ভেবেছিলাম সম্ভবত আপনিও এটি চেষ্টা করতে চান:

_time() if   set -- "${IFS+IFS=\$2;}" "$IFS" "$@" && IFS='
';      then set -- "$1" "$2" "$*"; unset IFS
             eval "$1 $TIME ${3#"$1"?"$2"?}"
        fi

$IFSবিট প্রধানত সম্পর্কে $*। এটি গুরুত্বপূর্ণ যে ( subshell bit )হয় একটি শেল সম্প্রসারণের ফলাফলের তাই অর্ডার parsable স্ট্রিং আমি ব্যবহারের মধ্যে আর্গুমেন্ট প্রসারিত করার জন্য "$*" (না eval "$@", উপায় দ্বারা, যদি না আপনি args নির্মাণ করে চলেছি নির্দিষ্ট সব শূণ্যস্থান উপর যোগদান করা যাবে) । আরোগুলির মধ্যে বিভাজিত ডিলিমিটারটি "$*"প্রথম বাইট হয় $IFSএবং সুতরাং এর মান নির্দিষ্ট না করেই এগিয়ে যাওয়া বিপজ্জনক হতে পারে। সুতরাং ফাংশন সংরক্ষণ $IFS, একটি থেকে এটি সেট করে \nদীর্ঘ যথেষ্ট ewline set ... "$*"মধ্যে "$3", unsetএটি গুলি, তারপর এর মান রিসেট যদি এটা পূর্বে এক ছিল।

এখানে একটি ছোট ডেমো:

TIME='set -x; time'
_time \( 'echo "$(echo any number of subshells)"' \
         'command -V time'                        \
         'hash time'                              \
      \) 'set +x'

আপনি দেখতে পাচ্ছেন যে আমি $TIMEসেখানে দুটি কমান্ড রেখেছি - যে কোনও সংখ্যা ভাল - এমনকি কোনওটিই নয় - তবে নিশ্চিত হয়ে নিন যে এটি পালিয়ে গেছে এবং যথাযথভাবে উদ্ধৃত হয়েছে - এবং যুক্তিগুলি একই রকম হয় _time()। মৃত্যুদন্ড কার্যকর করার সময় এগুলি সমস্তই একটি একক কমান্ড স্ট্রিংয়ে যুক্ত হবে - তবে প্রতিটি আর্গ নিজস্ব \nইওলাইন পায় এবং সেগুলি তুলনামূলকভাবে সহজেই ছড়িয়ে যায়। অন্যথায় আপনি যদি চান তবে এগুলিকে একটি করে \nলম্পট করতে পারেন এবং সেগুলি ইওলাইনস বা আধা-কোলনে বা আপনার কাছে কী আলাদা করতে পারেন। কেবলমাত্র নিশ্চিত হয়ে নিন যে কোনও একক যুক্তি একটি কমান্ডের প্রতিনিধিত্ব করে যা আপনি যখন কল করবেন তখন কোনও স্ক্রিপ্টে তার নিজস্ব লাইন লাগানো স্বাচ্ছন্দ্য বোধ করে। \(উদাহরণস্বরূপ, ঠিক আছে, যতক্ষণ এটি শেষ পর্যন্ত অনুসরণ করা হয় \)। মূলত সাধারণ জিনিস।

evalউপরের স্নিপেটটি কখন তা খাওয়ানো হবে তা দেখে মনে হচ্ছে:

+ eval 'IFS=$2;set -x; time (
echo "$(echo any number of subshells)"
command -V time
hash time
)
set +x'

এবং এর ফলাফলগুলি দেখতে দেখতে ...

আউটপুট

+++ echo any number of subshells
++ echo 'any number of subshells'
any number of subshells
++ command -V time
time is a shell keyword
++ hash time
bash: hash: time: not found

real    0m0.003s
user    0m0.000s
sys     0m0.000s
++ set +x

hashত্রুটি নির্দেশ করে যে আমি একজন না /usr/bin/timeইনস্টল (কারণ আমি না) এবং commandএর আমাদের জানান যা সময় চলমান যাক। ট্রেলিং set +xহ'ল একটি আদেশ যা পরে সম্পাদিত হয় time (যা সম্ভব) - evalকোনও কিছুর ইনগ্রে করার সময় ইনপুট কমান্ডগুলি সম্পর্কে সতর্কতা অবলম্বন করা জরুরী ।


এটি না করার কোনও কারণ _time() { eval "$TIME $@"; }? কোনও ফাংশনটি ব্যবহার করে ভেরিয়েবলের জন্য আলাদা সুযোগের (সাবসেলের জন্য কোনও সমস্যা নয়) পরিচয় করিয়ে দেওয়ার অসুবিধা রয়েছে
স্টাফেন চেজেলাস

@ স্টাফেনচেজেলাস - "$@"সম্প্রসারণের উদ্ধৃতিগুলির কারণে । আমি একক evalযুক্তি পছন্দ করি - অন্যথায় এটি ভয়ঙ্কর হয়ে পড়ে। উম্মম .... যদিও আপনি আলাদা স্কোপটির অর্থ কী? আমি ভেবেছিলাম যে এটি কেবল functionফাংশন ছিল ...
মাইকেসার্ভ

evalকার্যকর করার আগে এর আরগগুলিতে যোগ দেয় যা আপনি খুব বিভ্রান্ত উপায়ে করার চেষ্টা করছেন। আমি বলতে চাইছি যে এটি _time 'local var=1; blah'সেই varস্থানীয় করে তুলবে _time, বা এটি সেই ফাংশনের _time 'echo "$#"'মুদ্রণ করবে $#, _timeকলারের নয়।
স্টাফেন চেজেলাস

@ স্টাফেনচাজেলাস - আপনার জন্য এখানে দুটি ট্যাব সম্পূর্ণ হয়েছে। ডান - evalশূন্যস্থানগুলিতে এর আরোগুলি সন্নিবেশিত করে - যা আপনি যেমন বলেন ঠিক তেমন আমি এখানে যা করি তা - যদিও এটি কোনও প্রাথমিক উদ্দেশ্য ছিল না। আমি এটি ঠিক করতে যাচ্ছি। evalবিপক্ষ "$*"হিসাবে ইঙ্গিত করা "$@"অভ্যাসটি যখন আমি command not foundভুল জায়গায় আরগস যুক্ত হয়েছিল তখন আমি অনেক রান-ইন করার পরে বাছাই করি । যাই হোক না কেন, শেষ পর্যন্ত ফাংশনে আরগগুলি কার্যকর করা হলেও, অনুরোধে এগুলি প্রসারিত করা যথেষ্ট সহজ, আমি মনে করি। এটি আমি "$#"যাই হোক না কেন সঙ্গে কি হবে।
মাইকজার্ভ

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