বাশ ফাংশনে রিটার্ন মান


303

আমি বাশ স্ক্রিপ্টের সাথে কাজ করছি এবং আমি কোনও ফিরতি মান মুদ্রণের জন্য একটি ফাংশন সম্পাদন করতে চাই:

function fun1(){
  return 34
}
function fun2(){
  local res=$(fun1)
  echo $res
}

আমি যখন মৃত্যুদন্ড কার্যকর করি fun2, এটি "34" মুদ্রণ করে না। কেন এই ক্ষেত্রে?


8
returnআপনার ক্ষেত্রে মূলত exit codeযা হয় তা থেকে একই রকম 0 - 255echo@ সেপটি দ্বারা প্রস্তাবিত হিসাবে ব্যবহার করুন । প্রস্থান কোডগুলি ক্যাপচার করা যেতে পারে $?
ডিভনুল

1
এই ক্ষেত্রে ইতোমধ্যে ফান 1 এ প্রতিধ্বনি ব্যবহার করা আরও অনেক নমনীয়। এটি ইউনিক্স-প্রোগ্রামিংয়ের ধারণা: প্রতিধ্বনির ফলাফলগুলি স্ট্যান্ডার্ড আউটপুটে প্রেরণ করে যা এরপরে res = res (ফান 1) দিয়ে অন্য ফাংশনগুলি দ্বারা পুনরায় ব্যবহার করা যেতে পারে - বা অন্য ফাংশনে সরাসরি পাইপ করা যেতে পারে:function a() { echo 34; } function b() { while read data; do echo $data ; done ;} a | b
আর্নে

এটি করার সঠিক উপায় হ'ল কোনও ফাংশনে শীর্ষ স্তরের জিনিসগুলি রাখা এবং বাশের গতিশীল স্কোপিং বিধি সহ একটি স্থানীয় ব্যবহার করা। আমি প্রদর্শনের জন্য একটি উত্তর তৈরি করব, এটি একটি সুপরিচিত বৈশিষ্ট্য নয় তবে এটি সম্পূর্ণ সমর্থিত।
অলিভার


উত্তর:


372

যদিও বাশের একটি returnবিবৃতি রয়েছে, তবে এটির সাহায্যে আপনি কেবলমাত্র যা নির্দিষ্ট করতে পারবেন তা হ'ল ফাংশনের নিজস্ব exitস্ট্যাটাস (এর মধ্যে একটি মান 0এবং 255"যার অর্থ" সাফল্য ")। returnআপনি যা চান তা তাই নয়।

আপনি আপনার returnবিবৃতিটিকে একটি echoবিবৃতিতে রূপান্তর করতে চাইতে পারেন - এই ধরণের $()ধনুর্বন্ধনী ব্যবহার করে আপনার ফাংশন আউটপুট ক্যাপচার করা যেতে পারে , যা দেখতে আপনি ঠিক চান বলে মনে হয়।

এখানে একটি উদাহরণ:

function fun1(){
  echo 34
}

function fun2(){
  local res=$(fun1)
  echo $res
}

রিটার্ন মান পাওয়ার আরেকটি উপায় (যদি আপনি কেবল একটি পূর্ণসংখ্যা 0-255 ফেরত করতে চান) হয় $?

function fun1(){
  return 34
}

function fun2(){
  fun1
  local res=$?
  echo $res
}

এছাড়াও নোট করুন যে আপনি বুলিয়ান লজিক ব্যবহার করতে রিটার্ন মানটি ব্যবহার করতে পারেন তবেই কোনও মান ফেরত দিলে fun1 || fun2চলবে । ডিফল্ট রিটার্ন মান হ'ল ফাংশনের মধ্যে সম্পাদিত সর্বশেষ বিবৃতিটির প্রস্থান মূল্য।fun2fun10


2
আপনাকে এক্সিকিউট করতে হবে fun1এবং তারপরে রিটার্ন মানটি সংরক্ষণ করা হবে $?। যদিও আমি এটি করার সুপারিশ করব না…
তামাসল

9
কেন ব্যবহার $?করবেন না ?
পিথিকোস

147
না, আমার অভিশাপ ফেরতের মান দরকার । প্রতিধ্বনির সাথে জাহান্নামে।
টোমা জ্যাটো - মনিকা 1921

7
এই পরিবেশে ব্লাউহিরন, এই ||নির্মাণের সাথে 0 এর একটি প্রস্থান কোড সাফল্য হিসাবে বিবেচিত এবং তাই "সত্য" " অ-শূন্য ত্রুটি এবং তাই মিথ্যা। fun1 || fun2"ফান 1 সাফল্য ফিরিয়ে দেয় বা ফান 2 সাফল্য ফিরিয়ে দেয়" এর জন্য শর্টহ্যান্ড হিসাবে ভাবুন প্রকৃত রিটার্নকে নিজেরাই মূল্য দেয়।
ডেভিডা

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

68

$(...)স্ট্যান্ডআউটে প্রেরিত পাঠ্যটি এতে থাকা কমান্ড দ্বারা ক্যাপচার করে। returnstdout আউটপুট না। $?শেষ কমান্ডের ফলাফল কোড রয়েছে।

fun1 (){
  return 34
}

fun2 (){
  fun1
  local res=$?
  echo $res
}

5
হ্যাঁ যা returnসেটিং জন্য ব্যবহৃত $?হয় exit status। উপরের উদাহরণে, fun1এর exit statusহবে 34। এছাড়াও নোট করুন যে $(...)নির্দিষ্ট কমান্ড থেকে stdout ছাড়াও stderr ক্যাপচার।
swoop81

58

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

শেল কমান্ডগুলি পাইপ (ওরফে স্ট্রিম) দ্বারা সংযুক্ত থাকে এবং "আসল" প্রোগ্রামিং ভাষার মতো মৌলিক বা ব্যবহারকারী-সংজ্ঞায়িত ডেটা ধরণের নয়। কমান্ডের জন্য ফেরতের মূল্যের মতো কোনও জিনিস নেই, কারণ সম্ভবত এটির ঘোষণা করার কোনও সঠিক উপায় নেই। এটি ম্যান-পৃষ্ঠায় বা --helpকমান্ডের আউটপুটে ঘটতে পারে তবে উভয়ই কেবল মানব-পঠনযোগ্য এবং তাই বাতাসে লেখা হয়।

যখন কোনও কমান্ড ইনপুট পেতে চায় তখন এটি তার ইনপুট স্ট্রিম, বা যুক্তি তালিকা থেকে তা পড়ে। উভয় ক্ষেত্রে পাঠ্যের স্ট্রিংগুলি বিশ্লেষণ করতে হবে।

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

encrypt() {
    gpg -c -o- $1 # encrypt data in filename to stdout (asks for a passphrase)
}

encrypt public.dat > private.dat # write function result to file

অন্যরা যেমন এই থ্রেডে লিখেছেন, কলার $()আউটপুট ক্যাপচার করতে কমান্ড প্রতিস্থাপনও ব্যবহার করতে পারেন।

সমান্তরালভাবে, ফাংশনটি gpg(GnuPG) এর প্রস্থান কোডটিকে "ফিরিয়ে" দেবে । অন্যান্য ভাষার ভাষাগুলি যে বোনাসের কাছে নেই, বা শেল ফাংশনগুলির একটি "শ্মুটজেফেক্ট" হিসাবে আপনার মেজাজের উপর নির্ভর করে প্রস্থান কোডটি ভাবেন। এই স্থিতিটি, কনভেনশন অনুসারে 0 সাফল্যের সাথে বা অন্য কোনও কিছুর জন্য 1-255 পরিসীমাতে পূর্ণসংখ্যা হয়। এটি পরিষ্কার করার জন্য: return(পছন্দ করুন exit) কেবল 0-255 থেকে একটি মান নিতে পারে এবং 0 টির চেয়ে অন্যান্য মানগুলি ত্রুটি নয়, প্রায়শই বলা হয়।

আপনি যখন returnস্ট্যাটাসের সাথে একটি স্পষ্ট মান প্রদান করবেন না তখন বাশ বিবৃতি / ফাংশন / কমান্ড এবং শেষের দিকের শেষ কমান্ড থেকে নেওয়া হবে। সুতরাং সর্বদা একটি স্থিতি থাকে এবং returnএটি সরবরাহ করার এক সহজ উপায়।


3
কমান্ড বনাম কমান্ডগুলি ব্যাখ্যা করার জন্য +1 এবং এটি কলারের কাছে ডেটা ফেরত পাঠানোর ধারণাকে কীভাবে প্রভাবিত করে
অলিভার

3
শেল প্রোগ্রামিংটি পাইপের মাধ্যমে কমান্ড সংযোগ স্থাপনের বিষয়ে বোঝানোর জন্য +1। অন্যান্য প্রোগ্রামিং ভাষাগুলি রিটার্নের ধরণের মাধ্যমে ফাংশন রচনা করে। টেক্সট স্ট্রিমের মাধ্যমে বাশ কমান্ডগুলি রচনা করে।
জড়হালি

29

returnবিবৃতি ফাংশনের প্রস্থান কোড, একই হিসাবে সেট করে exitসমগ্র স্ক্রিপ্টের জন্য চেষ্টা করতে হবে।

শেষ কমান্ডের প্রস্থান কোডটি সর্বদা চলকটিতে উপলভ্য $?

function fun1(){
  return 34
}

function fun2(){
  local res=$(fun1)
  echo $? # <-- Always echos 0 since the 'local' command passes.

  res=$(fun1)
  echo $?  #<-- Outputs 34
}

19

অন্যান্য উত্তরের সমস্যা হ'ল তারা হয় একটি গ্লোবাল ব্যবহার করেন যা কোনও কল চেইনে থাকা অবস্থায় ওভাররাইট করা যেতে পারে, বা echoযার অর্থ আপনার ফাংশন ডায়াগনস্টিক তথ্য আউটপুট দিতে পারে না (আপনি আপনার ফাংশনটি ভুলে যাবেন এটি এবং "ফলাফল" করবে, অর্থাৎ প্রত্যাবর্তন evalমানটিতে আপনার কলার প্রত্যাশার চেয়ে আরও বেশি তথ্য থাকবে যা অদ্ভুত বাগের দিকে পরিচালিত করবে) বা যা খুব ভারী এবং হ্যাকি।

এটি করার সঠিক উপায় হ'ল শীর্ষ স্তরের জিনিসগুলি কোনও ফাংশনে রাখা এবং localবাশের গতিশীল স্কোপিং বিধি সহ একটি ব্যবহার করা । উদাহরণ:

func1() 
{
    ret_val=hi
}

func2()
{
    ret_val=bye
}

func3()
{
    local ret_val=nothing
    echo $ret_val
    func1
    echo $ret_val
    func2
    echo $ret_val
}

func3

এই ফলাফল

nothing
hi
bye

ডায়নামিক স্কোপিং মানে ret_valকলারের উপর নির্ভর করে কোনও ভিন্ন অবজেক্টের দিকে নির্দেশ করা! এটি লেক্সিকাল স্কোপিং থেকে পৃথক, যা বেশিরভাগ প্রোগ্রামিং ভাষা ব্যবহার করে। এটি আসলে একটি ডকুমেন্টেড বৈশিষ্ট্য , যা সহজেই মিস করা সহজ এবং খুব ভালভাবে ব্যাখ্যা করা যায় না, এটির জন্য ডকুমেন্টেশন এখানে রয়েছে (জোর দেওয়া আমার):

স্থানীয় বিল্টিনের সাথে ফাংশনের স্থানীয় ভেরিয়েবলগুলি ঘোষিত হতে পারে। এই ভেরিয়েবলগুলি কেবল ফাংশনটিতে দৃশ্যমান এবং কমান্ডগুলি এটির অনুরোধ করে

সি / সি ++ / পাইথন / জাভা / সি # / জাভাস্ক্রিপ্ট ব্যাকগ্রাউন্ডવાળા কারও পক্ষে এটি সম্ভবত সবচেয়ে বড় প্রতিবন্ধকতা: ব্যাশে ফাংশনগুলি ফাংশন নয়, সেগুলি আদেশ হয় এবং এরূপ আচরণ করে: তারা আউটপুট করতে পারে stdout/ stderr, তারা পাইপ করতে পারে / আউট, তারা একটি প্রস্থান কোড ফিরে আসতে পারে। মূলত স্ক্রিপ্টে একটি কমান্ড সংজ্ঞায়িত করা এবং কমান্ড লাইন থেকে ডাকা যেতে পারে এমন একটি এক্সিকিউটেবল তৈরির মধ্যে কোনও পার্থক্য নেই।

সুতরাং আপনার স্ক্রিপ্টটি এভাবে লেখার পরিবর্তে:

top-level code 
bunch of functions
more top-level code

এটি লিখুন:

# define your main, containing all top-level code
main() 
bunch of functions
# call main
main  

যেখানে হিসাবে main()ঘোষিত ret_valহয় localএবং অন্যান্য সমস্ত ফাংশনগুলির মাধ্যমে মানগুলি ফেরত দেয় ret_val

নিম্নলিখিত ইউনিক্স এবং লিনাক্স প্রশ্নটিও দেখুন: শেল কার্যক্রমে স্থানীয় চলকগুলির সুযোগ

আরেকটি, পরিস্থিতির উপর নির্ভর করে সম্ভবত আরও ভাল সমাধান হ'ল ya.teck দ্বারা পোস্ট করা একটি যা ব্যবহার করে local -n


16

এটি অর্জনের অন্য উপায় হ'ল নাম উল্লেখ (বাশ 4.3+ প্রয়োজন)।

function example {
  local -n VAR=$1
  VAR=foo
}

example RESULT
echo $RESULT

2
ভাবছি কি কেউ -n <name>=<reference>নেই: নব নির্মিত পরিবর্তনশীল অন্য এক একটি রেফারেন্স দ্বারা নির্দিষ্ট করে তোলে <reference><name>রেফারেন্সড ভেরিয়েবলের উপর আরও কার্য সম্পাদন করা উচিত।
ভ্যালারিও

7

ফাংশনটি সংজ্ঞায়িত হয়েছে এমন স্ক্রিপ্টে চলতে থাকলে আমি নিম্নলিখিতগুলি করতে পছন্দ করি:

POINTER= # used for function return values

my_function() {
    # do stuff
    POINTER="my_function_return"
}

my_other_function() {
    # do stuff
    POINTER="my_other_function_return"
}

my_function
RESULT="$POINTER"

my_other_function
RESULT="$POINTER"

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

my_function() {
    echo "-> my_function()"
    # do stuff
    POINTER="my_function_return"
    echo "<- my_function. $POINTER"
}

4

অন্যের দুর্দান্ত পোস্টগুলিতে অ্যাড-অন হিসাবে, এখানে এই কৌশলগুলির সংক্ষিপ্ত বিবরণ রয়েছে:

  • গ্লোবাল ভেরিয়েবল সেট করুন
  • একটি গ্লোবাল ভেরিয়েবল সেট করুন, যার নাম আপনি ফাংশনে পাস করেছেন
  • রিটার্ন কোডটি সেট করুন (এবং এটি দিয়ে $?)
  • কিছু প্রতিবেদন 'প্রতিধ্বনি' করুন (এবং এটি MYVAR = $ (myfunction)) এর সাথে তুলুন)

বাশ ফাংশন থেকে মূল্য ফেরত


এটি সর্বোত্তম উত্তর, কারণ নিবন্ধটি পরিষ্কারভাবে সমস্ত বিকল্প নিয়ে আলোচনা করে।
mzimmermann

-2

একাধিক রিটার্ন মানগুলির জন্য উইন্ডোতে অ্যারে ব্যবহার করে গিট ব্যাশ

বেস কোড:

#!/bin/bash

##A 6-element array used for returning
##values from functions:
declare -a RET_ARR
RET_ARR[0]="A"
RET_ARR[1]="B"
RET_ARR[2]="C"
RET_ARR[3]="D"
RET_ARR[4]="E"
RET_ARR[5]="F"


function FN_MULTIPLE_RETURN_VALUES(){

   ##give the positional arguments/inputs
   ##$1 and $2 some sensible names:
   local out_dex_1="$1" ##output index
   local out_dex_2="$2" ##output index

   ##Echo for debugging:
   echo "running: FN_MULTIPLE_RETURN_VALUES"

   ##Here: Calculate output values:
   local op_var_1="Hello"
   local op_var_2="World"

   ##set the return values:
   RET_ARR[ $out_dex_1 ]=$op_var_1
   RET_ARR[ $out_dex_2 ]=$op_var_2
}


echo "FN_MULTIPLE_RETURN_VALUES EXAMPLES:"
echo "-------------------------------------------"
fn="FN_MULTIPLE_RETURN_VALUES"
out_dex_a=0
out_dex_b=1
eval $fn $out_dex_a $out_dex_b  ##<--Call function
a=${RET_ARR[0]} && echo "RET_ARR[0]: $a "
b=${RET_ARR[1]} && echo "RET_ARR[1]: $b "
echo
##----------------------------------------------##
c="2"
d="3"
FN_MULTIPLE_RETURN_VALUES $c $d ##<--Call function
c_res=${RET_ARR[2]} && echo "RET_ARR[2]: $c_res "
d_res=${RET_ARR[3]} && echo "RET_ARR[3]: $d_res "
echo
##----------------------------------------------##
FN_MULTIPLE_RETURN_VALUES 4 5  ##<---Call function
e=${RET_ARR[4]} && echo "RET_ARR[4]: $e "
f=${RET_ARR[5]} && echo "RET_ARR[5]: $f "
echo
##----------------------------------------------##


read -p "Press Enter To Exit:"

পরীক্ষিত আউটপুট:

FN_MULTIPLE_RETURN_VALUES EXAMPLES:
-------------------------------------------
running: FN_MULTIPLE_RETURN_VALUES
RET_ARR[0]: Hello
RET_ARR[1]: World

running: FN_MULTIPLE_RETURN_VALUES
RET_ARR[2]: Hello
RET_ARR[3]: World

running: FN_MULTIPLE_RETURN_VALUES
RET_ARR[4]: Hello
RET_ARR[5]: World

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