শেল স্ক্রিপ্টে ডাকা ফাংশন থেকে মান ফেরত


126

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

lockdir="somedir"
test() {
    retval=""

    if mkdir "$lockdir"
        then    # Directory did not exist, but it was created successfully
            echo >&2 "successfully acquired lock: $lockdir"
            retval="true"
        else
            echo >&2 "cannot acquire lock, giving up on $lockdir"
            retval="false"
    fi
    return retval
}


retval=test()
if [ "$retval" == "true" ]
    then
        echo "directory not created"
    else
        echo "directory already created"
fi

আপনার প্রশ্নের সাথে সম্পর্কিত নয়, তবে যাইহোক ... আপনি যদি লক পাওয়ার চেষ্টা করছেন তবে আপনি "লকফিল" কমান্ডটি ব্যবহার করতে পারেন।
ভেক্টর হেরাইজ

উত্তর:


277

আপনার পছন্দ মতো কোনও বাশ ফাংশন সরাসরি কোনও স্ট্রিং ফিরিয়ে দিতে পারে না। আপনি তিনটি জিনিস করতে পারেন:

  1. একটি স্ট্রিং প্রতিধ্বনি করুন
  2. একটি প্রস্থান স্থিতি ফিরিয়ে দিন, যা কোনও সংখ্যা, স্ট্রিং নয়
  3. একটি পরিবর্তনশীল ভাগ করুন

এটি অন্য কয়েকটি শেলের ক্ষেত্রেও সত্য।

এই বিকল্পগুলির প্রত্যেকটি কীভাবে করবেন তা এখানে রয়েছে:

1. প্রতিধ্বনি স্ট্রিং

lockdir="somedir"
testlock(){
    retval=""
    if mkdir "$lockdir"
    then # Directory did not exist, but it was created successfully
         echo >&2 "successfully acquired lock: $lockdir"
         retval="true"
    else
         echo >&2 "cannot acquire lock, giving up on $lockdir"
         retval="false"
    fi
    echo "$retval"
}

retval=$( testlock )
if [ "$retval" == "true" ]
then
     echo "directory not created"
else
     echo "directory already created"
fi

২. প্রস্থান প্রস্থান স্থিতি

lockdir="somedir"
testlock(){
    if mkdir "$lockdir"
    then # Directory did not exist, but was created successfully
         echo >&2 "successfully acquired lock: $lockdir"
         retval=0
    else
         echo >&2 "cannot acquire lock, giving up on $lockdir"
         retval=1
    fi
    return "$retval"
}

testlock
retval=$?
if [ "$retval" == 0 ]
then
     echo "directory not created"
else
     echo "directory already created"
fi

3. ভাগ পরিবর্তনশীল

lockdir="somedir"
retval=-1
testlock(){
    if mkdir "$lockdir"
    then # Directory did not exist, but it was created successfully
         echo >&2 "successfully acquired lock: $lockdir"
         retval=0
    else
         echo >&2 "cannot acquire lock, giving up on $lockdir"
         retval=1
    fi
}

testlock
if [ "$retval" == 0 ]
then
     echo "directory not created"
else
     echo "directory already created"
fi

2
functionব্যাশ ফাংশন সংজ্ঞায়িত করতে কোনও কীওয়ার্ড ব্যবহার করবেন না । যে এটি কম পোর্টেবল করতে হবে। এটি সরানো হচ্ছে।
দিশির

2
আপনার তৃতীয় উদাহরণে, উত্তোলন কোনও পরিবেশের পরিবর্তনশীল নয়। এটি নিছক শেল ভেরিয়েবল। আপনি এটি রফতানি করলেই এটি পরিবেশের পরিবর্তনশীল হয়ে উঠবে। সম্ভবত তৃতীয় উদাহরণের শিরোনামটি "পরিবেশ পরিবর্তনশীল" এর পরিবর্তে "গ্লোবাল ভেরিয়েবল" হওয়া উচিত।
উইলিয়াম পার্সেল

4
দ্বিতীয় উদাহরণে, $? থেকে বরাদ্দ না দিয়ে, "যদি টেস্টলক; তারপরে ..." লেখা আরও বোকামিযুক্ত
উইলিয়াম পার্সেল

@ উইলিয়ামপ্রসেল আমি ভুল 'পরিবেশ' শব্দটি সরিয়েছি। চলুন "$" রাখি? শিক্ষাগত উদ্দেশ্য জন্য। আমি উইকি সম্প্রদায়কে সক্ষম করেছি, সুতরাং আপনি উত্তরটি উন্নত করতে মুক্ত হন ;-)
অলিব্রে

1
@ ম্যানুয়েলজর্ডান, ফাংশনগুলি কেবল প্রস্থান কোড এবং> & 2 লগগুলি স্টেডাররে ফিরে আসতে পারে, সুতরাং শেষ প্রতিধ্বনিটি স্টডআউটে লিখিত হয়, সুতরাং, কলিং ফাংশনটি কেবল স্টডআউটকে ক্যাপচার করে এবং স্টার্ডারকে নয়। এক্সিকিউশনটি এককভাবে থ্রেডড হিসাবে ধরে নেওয়া, TEST_LOCK_STATUS = "" বাইরের পদ্ধতির মতো একটি কাস্টম ভেরিয়েবল বজায় রাখা আরও ভাল বিকল্প যা টেস্টলক কল করার পরে যে কেউ ব্যবহার করতে পারে এবং পদ্ধতিটির শুরুতে প্রতিবার এটি পুনরায় সেট করতে পারে
কিসনা

16

আপনি খুব কঠোরভাবে কাজ করছেন। আপনার সম্পূর্ণ স্ক্রিপ্টটি হওয়া উচিত:

if mkdir "$lockdir" 2> /dev/null; then 
  echo lock acquired
else
  echo could not acquire lock >&2
fi

তবে এটি সম্ভবত খুব ভার্জোজ। আমি এটি কোড করব:

mkdir "$lockdir" || exit 1

তবে ফলাফল ত্রুটি বার্তাটি কিছুটা অস্পষ্ট।


1
অনুপস্থিত ত্রুটি বার্তাটি ঠিক করা যথেষ্ট সহজ, যদিও এটি আরও কিছুটা ভার্বোজ রয়েছে: mkdir "$lockdir" || { echo "could not create lock dir" >&2 ; exit 1 ; }( ;বন্ধ হওয়া কোঁকড়া ধনুর্বন্ধনীটির আগে লক্ষ্য করুন )। এছাড়াও, আমি প্রায়শই একটি ব্যর্থ ফাংশন সংজ্ঞায়িত করি যা একটি anচ্ছিক বার্তা প্যারামিটার নেয় যা এটি স্ট্ডারকে প্রিন্ট করে এবং তারপরে রিটার্ন কোড 1 দিয়ে প্রস্থান করে, আমাকে আরও বেশি পঠনযোগ্য ব্যবহার করতে সক্ষম করে mkdir "$lockdir" || fail "could not create lock dir"
blubberdiblub

@ ব্লুবার্ডিব্লুব: তবে ব্যর্থ ফাংশন "বর্তমান" ফাংশন বা স্ক্রিপ্ট থেকে বেরিয়ে আসতে পারে না, তাই না? সুতরাং আপনি cmd || fail "error msg" || return 1যদি এটি করতে চান তবে আপনাকে ব্যবহার করতে হবে, তাই না?
সর্বাধিক

@ ম্যাক্স বর্তমান ফাংশন নয়, এটি সঠিক। তবে এটি বর্তমান স্ক্রিপ্ট থেকে প্রস্থান করবে, যতক্ষণ না আপনি এটিকে আদেশ হিসাবে ডেকেছেন এবং এটি উত্স হিসাবে নেই didn't আমি সাধারণত failমারাত্মক পরিস্থিতিতে ব্যবহৃত যেমন একটি ফাংশন মনে করি ।
blubberdiblub

12

যদি এটি কেবল একটি সত্য / মিথ্যা পরীক্ষা হয় তবে return 0সাফল্যের return 1জন্য এবং ব্যর্থতার জন্য আপনার কার্য করুন । পরীক্ষাটি তখন হবে:

if function_name; then
  do something
else
  error condition
fi

ঠিক আমি খুঁজছেন ছিল কি.
স্যামুয়েল

প্যারামিটারাইজড ফাংশনগুলির জন্যও এই স্বরলিপিটি ব্যবহার করার কোনও উপায় আছে?
অ্যালেক্স

@ আলেক্স আপনি "প্যারামিটারাইজড ফাংশন" বলতে যা বোঝায় তার উদাহরণ দিতে পারেন?
গ্লেন জ্যাকম্যান

'myCopyFunc {OUR উত্স} $ ST DEST}', সাফল্যে 0 ফিরে আসুন। যেমন এই ইস্যুতে যেমন: স্ট্যাকওভারফ্লো.com
অ্যালেক্স

হ্যাঁ, এটি পুরোপুরি ঠিক আছে
গ্লেন জ্যাকম্যান

2

আমি মনে করি ব্যর্থ (গ্লেন জ্যাকম্যান) এর জন্য স্যাক / 1 এর জন্য 0 ফিরে আসছি এবং অলিবারের স্পষ্ট এবং ব্যাখ্যামূলক উত্তরটি সব বলেছে; ফলাফলগুলি বাইনারি না হওয়ার ক্ষেত্রে কেবল এক ধরণের "কম্বো" পদ্ধতির উল্লেখ করার জন্য এবং ফলাফলকে "প্রতিধ্বনিত" করার পরিবর্তে আপনি একটি পরিবর্তনশীল সেট করতে পছন্দ করেন (উদাহরণস্বরূপ যদি আপনার ফাংশনটিও যদি কিছু কিছু প্রতিধ্বনি করে মনে করে তবে এই পদ্ধতির সাথে যোগাযোগ করা হবে) কাজ করে না). তখন কি? (নীচে বোর্ন শেল)

# Syntax _w (wrapReturn)
# arg1 : method to wrap
# arg2 : variable to set
_w(){
eval $1
read $2 <<EOF
$?
EOF
eval $2=\$$2
}

যেমন (হ্যাঁ, উদাহরণটি কিছুটা নির্বোধ, এটি কেবল একটি .. উদাহরণ)

getDay(){
  d=`date '+%d'`
  [ $d -gt 255 ] && echo "Oh no a return value is 0-255!" && BAIL=0 # this will of course never happen, it's just to clarify the nature of returns
  return $d
}

dayzToSalary(){
  daysLeft=0
  if [ $1 -lt 26 ]; then 
      daysLeft=`expr 25 - $1`
  else
     lastDayInMonth=`date -d "`date +%Y%m01` +1 month -1 day" +%d`
     rest=`expr $lastDayInMonth - 25`
     daysLeft=`expr 25 + $rest`
  fi
  echo "Mate, it's another $daysLeft days.."
}

# main
_w getDay DAY # call getDay, save the result in the DAY variable
dayzToSalary $DAY

1

কোনও ফাংশনে যাওয়ার জন্য আপনার কাছে কিছু পরামিতি রয়েছে এবং এর বিনিময়ে একটি মান চান। এখানে আমি একটি ফাংশনের আর্গুমেন্ট হিসাবে "12345" পাস করছি এবং ভেরিয়েবল XYZ ফেরত প্রক্রিয়াকরণের পরে যা ভ্যালুতে নির্ধারিত হবে

#!/bin/bash
getValue()
{
    ABC=$1
    XYZ="something"$ABC
    echo $XYZ
}


VALUE=$( getValue "12345" )
echo $VALUE

আউটপুট:

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