বাশ ফাংশন ডেকরেটার


10

পাইথনে আমরা কোড সহ ফাংশনগুলি সাজাতে পারি যা ফাংশনগুলির বিরুদ্ধে স্বয়ংক্রিয়ভাবে প্রয়োগ করা হয় এবং কার্যকর করা হয়।

বাশে কি তেমন কোনও বৈশিষ্ট্য রয়েছে?

আমি বর্তমানে যে স্ক্রিপ্টটিতে কাজ করছি তাতে আমার কাছে কিছু বয়লারপ্লেট রয়েছে যা প্রয়োজনীয় যুক্তিগুলি পরীক্ষা করে এবং উপস্থিত না থাকলে প্রস্থান করে - এবং ডিবাগিং পতাকাটি নির্দিষ্ট করা থাকলে কিছু বার্তা প্রদর্শন করে।

দুর্ভাগ্যক্রমে আমাকে প্রতিটি ফাংশনে এই কোডটি পুনরায় প্রবেশ করতে হবে এবং আমি যদি এটি পরিবর্তন করতে চাই তবে আমাকে প্রতিটি ফাংশনটি সংশোধন করতে হবে।

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


কার্যকারিতা আর্গুমেন্ট যাচাই করার জন্য আপনি সম্ভবত এই স্ক্রিপ্টটি আমি সম্প্রতি একসাথে টানতে পেরেছি, কমপক্ষে একটি প্রাথমিক পয়েন্ট হিসাবে।
ডিমো 414

উত্তর:


12

zshবেনামী ফাংশন এবং ফাংশন কোড সহ একটি বিশেষ সাহসী অ্যারে রয়েছে এতে এটি অনেক সহজ হবে । সঙ্গে bashতবে আপনি ভালো কিছু করতে পারে:

decorate() {
  eval "
    _inner_$(typeset -f "$1")
    $1"'() {
      echo >&2 "Calling function '"$1"' with $# arguments"
      _inner_'"$1"' "$@"
      local ret=$?
      echo >&2 "Function '"$1"' returned with exit status $ret"
      return "$ret"
    }'
}

f() {
  echo test
  return 12
}
decorate f
f a b

যা আউটপুট হবে:

Calling function f with 2 arguments
test
Function f returned with exit status 12

আপনার ফাংশনটি দু'বার সজ্জিত করতে আপনি দুবার ডেকোরেট কল করতে পারবেন না।

সহ zsh:

decorate()
  functions[$1]='
    echo >&2 "Calling function '$1' with $# arguments"
    () { '$functions[$1]'; } "$@"
    local ret=$?
    echo >&2 "function '$1' returned with status $ret"
    return $ret'

স্টিফেন - typesetপ্রয়োজনীয়? এটি অন্যথায় এটি ঘোষণা করবে না?
মাইক্রজারভ

@mikeserv, eval "_inner_$(typeset -f x)"সৃষ্টি _inner_xমূল একটি সঠিক অনুলিপি হিসেবে x(হিসাবে একই functions[_inner_x]=$functions[x]মধ্যে zsh)।
স্টাফেন চেজেলাস

আমি তা পেয়েছি - তবে কেন আপনার মোটেই দু'জনের দরকার?
মাইক্রজারভ

আপনি একটি ভিন্ন প্রেক্ষাপটে প্রয়োজন অন্যথায় আপনি ধরতে পারব না ভেতরের 'র return
স্টাফেন চেজেলাস

1
আমি তোমাকে সেখানে অনুসরণ করি না আমার উত্তরটি পাইথন সাজসজ্জারকে কী বলে আমি বুঝতে পারি তার
স্টাফেন চ্যাজেলাস

5

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

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

ঘোষণা করা

আপনার কেবল এমন একটি ফাংশন প্রয়োজন যা অন্যান্য ফাংশনগুলি ঘোষণা করে।

_fn_init() { . /dev/fd/4 ; } 4<<INIT
    ${1}() { $(shift ; printf %s\\n "$@")
     } 4<<-REQ 5<<-\\RESET
            : \${_if_unset?shell will ERR and print this to stderr}
            : \${common_param="REQ/RESET added to all funcs"}
        REQ
            _fn_init $(printf "'%s' " "$@")
        RESET
INIT

চালাও এটা

এখানে আমি _fn_initআমাকে একটি ক্রিয়াকলাপ ডেকে আনার আহ্বান জানাই fn

set -vx
_fn_init fn \
    'echo "this would be command 1"' \
    'echo "$common_param"'

#OUTPUT#
+ _fn_init fn 'echo "this would be command 1"' 'echo "$common_param"'
shift ; printf %s\\n "$@"
++ shift
++ printf '%s\n' 'echo "this would be command 1"' 'echo "$common_param"'
printf "'%s' " "$@"
++ printf ''\''%s'\'' ' fn 'echo "this would be command 1"' 'echo "$common_param"'
#ALL OF THE ABOVE OCCURS BEFORE _fn_init RUNS#
#FIRST AND ONLY COMMAND ACTUALLY IN FUNCTION BODY BELOW#
+ . /dev/fd/4

    #fn AFTER _fn_init .dot SOURCES IT#
    fn() { echo "this would be command 1"
        echo "$common_param"
    } 4<<-REQ 5<<-\RESET
            : ${_if_unset?shell will ERR and print this to stderr}
            : ${common_param="REQ/RESET added to all funcs"}
        REQ
            _fn_init 'fn' \
               'echo "this would be command 1"' \
               'echo "$common_param"'
        RESET

REQUIRED টি

যদি আমি এই ফাংশনটি কল করতে চাই তবে পরিবেশের পরিবর্তনশীল _if_unsetসেট না করা এটি মারা যায় ।

fn

#OUTPUT#
+ fn
/dev/fd/4: line 1: _if_unset: shell will ERR and print this to stderr

শেল ট্রেসের ক্রমটি দয়া করে নোট করুন - আনসেট থাকা fnঅবস্থায় _if_unsetকেবল যখন ডাকা হয় তখনই এটি ব্যর্থ হয় না, তবে এটি কখনই প্রথম স্থানে চলে না । এখানে-নথি বিস্তারের সাথে কাজ করার সময় এটি বোঝার জন্য সর্বাধিক গুরুত্বপূর্ণ বিষয় - এগুলি সর্বদা প্রথমে হওয়া উচিত কারণ তারা সব <<inputপরে।

ত্রুটিটি এসেছিল /dev/fd/4কারণ পিতামাত্ত শেলটি ইনপুটটিকে ফাংশনে দেওয়ার আগে before ইনপুটটিকে মূল্যায়ন করে। প্রয়োজনীয় পরিবেশের জন্য এটি পরীক্ষা করা সবচেয়ে সহজতম উপায়।

যাইহোক, ব্যর্থতা সহজেই প্রতিকার করা যায়।

_if_unset=set fn

#OUTPUT#
+ _if_unset=set
+ fn
+ echo 'this would be command 1'
this would be command 1
+ echo 'REQ/RESET added to all funcs'
REQ/RESET added to all funcs

নমনীয়

ভেরিয়েবল common_paramদ্বারা ঘোষিত প্রতিটি কার্যের জন্য ইনপুটটিতে একটি ডিফল্ট মানকে মূল্যায়ন করা হয় _fn_init। তবে সেই মানটি অন্য যে কোনও ক্ষেত্রেও পরিবর্তনযোগ্য যা একইভাবে ঘোষিত প্রতিটি কার্যক্রমে সম্মানিত হবে। আমি এখন শেলের চিহ্নগুলি ছেড়ে দেব - আমরা এখানে কোনও অরক্ষিত অঞ্চল বা কোনও কিছুর মধ্যে যাচ্ছি না।

set +vx
_fn_init 'fn' \
               'echo "Hi! I am the first function."' \
               'echo "$common_param"'
_fn_init 'fn2' \
               'echo "This is another function."' \
               'echo "$common_param"'
_if_unset=set ;

উপরে আমি দুটি ফাংশন এবং সেট ঘোষণা করি _if_unset। এখন, উভয় ফাংশন কল করার আগে, আমি আনসেট করব common_paramযাতে আপনি দেখতে পাবেন যে আমি তাদের কল করার পরে তারা সেগুলি সেট করবে।

unset common_param ; echo
fn ; echo
fn2 ; echo

#OUTPUT#
Hi! I am the first function.
REQ/RESET added to all funcs

This is another function.
REQ/RESET added to all funcs

এবং এখন কলারের সুযোগ থেকে:

echo $common_param

#OUTPUT#
REQ/RESET added to all funcs

তবে এখন আমি এটি পুরোপুরি অন্য কিছু হতে চাই:

common_param="Our common parameter is now something else entirely."
fn ; echo 
fn2 ; echo

#OUTPUT#
Hi! I am the first function.
Our common parameter is now something else entirely.

This is another function.
Our common parameter is now something else entirely.

আর আমি যদি আনসেট না করি _if_unset?

unset _if_unset ; echo
echo "fn:"
fn ; echo
echo "fn2:"
fn2 ; echo

#OUTPUT#
fn:
dash: 1: _if_unset: shell will ERR and print this to stderr

fn2:
dash: 1: _if_unset: shell will ERR and print this to stderr

রিসেট

আপনার যদি কোনও সময়ে ফাংশনটির স্থিতি পুনরায় সেট করতে হয় তবে এটি সহজেই হয়ে যায়। আপনার কেবলমাত্র (ফাংশন থেকে) করতে হবে:

. /dev/fd/5

5<<\RESETইনপুট ফাইল-বর্ণনাকারীতে প্রাথমিকভাবে ফাংশনটি ঘোষণার জন্য ব্যবহৃত যুক্তিগুলি সংরক্ষণ করেছি saved সুতরাং .dotগুন যে কোন সময়ে শেল প্রক্রিয়া এটি প্রথম স্থানে সেট আপ পুনরাবৃত্তি করবেন। এটি খুব সুন্দর, সত্যই এবং পুরোপুরি পুরোপুরি পোর্টেবল যদি আপনি পসিক্স আসলে ফাইল-বর্ণনাকারী ডিভাইস নোড পাথগুলি নির্দিষ্ট করে না (যা শেলটির প্রয়োজনীয়তা .dot) তবে এই বিষয়টি উপেক্ষা করতে আগ্রহী ।

আপনি সহজেই এই আচরণটি প্রসারিত করতে পারেন এবং আপনার ফাংশনের জন্য বিভিন্ন রাজ্যকে কনফিগার করতে পারেন।

আরো বেশী?

এটি সবেমাত্র পৃষ্ঠটি স্ক্র্যাচ করে। আমি প্রায়শই কোনও মূল ফাংশনের ইনপুটটিতে ঘোষিতযোগ্য কিছু সহায়ক সহায়ক ফাংশন এম্বেড করতে এই কৌশলগুলি ব্যবহার করি - উদাহরণস্বরূপ, $@প্রয়োজন হিসাবে অতিরিক্ত অবস্থানিক অ্যারেগুলির জন্য । আসলে - যেমনটি আমি বিশ্বাস করি এটি অবশ্যই এর খুব কাছাকাছি কিছু হতে হবে যা উচ্চতর অর্ডার শেলগুলি যাইহোক করে। আপনি দেখতে পারেন যে এগুলি খুব সহজেই প্রোগ্রামের নামকরণ হয়েছে।

আমি এমন একটি জেনারেটর ফাংশনও ঘোষণা করতে চাই যা সীমিত প্রকারের প্যারামিটার গ্রহণ করে এবং তারপর ল্যাম্বডা - বা একটি লাইন ফাংশনের লাইনের সাথে একক-ব্যবহার বা অন্যথায় স্কোপ-লিমিটেড বার্নার-ফাংশন সংজ্ঞায়িত করে - যা কেবল unset -fতখনই নিজের মাধ্যম. আপনি চারপাশে একটি শেল ফাংশন পাস করতে পারেন।


ফাইল বর্ণনাকারী ব্যবহার করে অতিরিক্ত জটিলতার সুবিধা কী eval?
স্টাফেন শেজেলাস

@ স্টেফেনচাজেলাস আমার দৃষ্টিকোণ থেকে কোন জটিলতা নেই। আসলে, আমি এটিকে অন্যভাবে দেখছি। এছাড়াও, উদ্ধৃতিটি আরও সহজ এবং .dotফাইল এবং স্ট্রিমগুলির সাথে কাজ করে যাতে আপনি একইরকম যুক্তি তালিকার সমস্যাগুলির মধ্যে না চলে যা অন্যথায় হতে পারে। তবুও, এটি সম্ভবত পছন্দের বিষয়। আমি অবশ্যই এটি পরিষ্কার বলে মনে করি - বিশেষত যখন আপনি স্পষ্টরূপে ওষুধ খাই where
মাইকজারভ

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

2

আমি মনে করি ফাংশন সম্পর্কিত তথ্য মুদ্রণের এক উপায়, যখন আপনি

প্রয়োজনীয় যুক্তিগুলি পরীক্ষা করুন এবং সেগুলি উপস্থিত না থাকলে প্রস্থান করুন - এবং কিছু বার্তা প্রদর্শন করুন

বাশ অন্তর্নির্মিত পরিবর্তন returnএবং / অথবা exitপ্রতিটি স্ক্রিপ্টের শুরুতে (বা কোনও ফাইলের মধ্যে আপনি প্রোগ্রাম চালানোর আগে প্রতিবার উত্স করেছেন)। সুতরাং আপনি টাইপ করুন

   #!/bin/bash
   return () {
       if [ -z $1 ] ; then
           builtin return
       else
           if [ $1 -gt 0 ] ; then
                echo function ${FUNCNAME[1]} returns status $1 
                builtin return $1
           else
                builtin return 0
           fi
       fi
   }
   foo () {
       [ 1 != 2 ] && return 1
   }
   foo

আপনি যদি এটি চালান তবে আপনি পাবেন:

   function foo returns status 1

আপনার প্রয়োজন হলে এটি ডিবাগিং ফ্ল্যাগের সাথে সহজেই আপডেট করা যেতে পারে, কিছুটা এরকম:

   #!/bin/bash
   VERBOSE=1
   return () {
       if [ -z $1 ] ; then
           builtin return
       else
           if [ $1 -gt 0 ] ; then
               [ ! -z $VERBOSE ] && [ $VERBOSE -gt 0 ] && echo function ${FUNCNAME[1]} returns status $1  
               builtin return $1
           else
               builtin return 0
           fi
       fi
    }    

ভেরিয়েবল VERBOSE সেট করা থাকলেই এই পদ্ধতিতে স্টেটমেন্ট কার্যকর করা হবে (কমপক্ষে আমি আমার স্ক্রিপ্টগুলিতে ভার্বোস ব্যবহার করব) use এটি অবশ্যই সাজসজ্জার ক্রিয়াকলাপের সমস্যাটি সমাধান করে না তবে এটি শূন্য-স্থিতি স্থিতির ক্ষেত্রে ফাংশন বার্তা প্রদর্শন করতে পারে।

আপনি স্ক্রিপ্ট থেকে প্রস্থান করতে চাইলে একইভাবে আপনি exitসমস্ত দৃষ্টান্তের পরিবর্তে পুনরায় সংজ্ঞা দিতে পারেন return

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

#!/bin/bash 
outer () { _
    inner1 () { _
        print "inner 1 command"
    }   
    inner2 () { _
        double_inner2 () { _
            print "double_inner1 command"
        } 
        double_inner2
        print "inner 2 command"
    } 
    inner1
    inner2
    inner1
    print "just command in outer"
}
foo_with_args () { _ $@
    print "command in foo with args"
}
echo command in body of script
outer
foo_with_args

এবং আউটপুট জন্য আমি এটি পেতে পারেন:

command in body of script
    outer: 
        inner1: 
            inner 1 command
        inner2: 
            double_inner2: 
                double_inner1 command
            inner 2 command
        inner1: 
            inner 1 command
        just command in outer
    foo_with_args: 1 2 3
        command in foo with args

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

#!/bin/bash 
set_indentation_for_print_function () {
    default_number_of_indentation_spaces="4"
    #                            number_of_spaces_of_current_function is set to (max number of inner function - 3) * default_number_of_indentation_spaces 
    #                            -3 is because we dont consider main function in FUNCNAME array - which is if your run bash decoration from any script,
    #                            decoration_function "_" itself and set_indentation_for_print_function.
    number_of_spaces_of_current_function=`echo ${#FUNCNAME[@]} | awk \
        -v default_number_of_indentation_spaces="$default_number_of_indentation_spaces" '
        { print ($1-3)*default_number_of_indentation_spaces}
        '`
    #                            actual indent is sum of default_number_of_indentation_spaces + number_of_spaces_of_current_function
    let INDENT=$number_of_spaces_of_current_function+$default_number_of_indentation_spaces
}
print () { # print anything inside function with proper indent
    set_indentation_for_print_function
    awk -v l="${INDENT:=0}" 'BEGIN {for(i=1;i<=l;i++) printf(" ")}' # print INDENT spaces before echo
    echo $@
}
_ () { # decorator itself, prints funcname: args
    set_indentation_for_print_function
    let INDENT=$INDENT-$default_number_of_indentation_spaces # we remove def_number here, because function has to be right from usual print
    awk -v l="${INDENT:=0}" 'BEGIN {for(i=1;i<=l;i++) printf(" ")}' # print INDENT spaces before echo
    #tput setaf 0 && tput bold # uncomment this for grey color of decorator
    [ $INDENT -ne 0 ] && echo "${FUNCNAME[1]}: $@" # here we avoid situation where decorator is used inside the body of script and not in the function
    #tput sgr0 # resets grey color
}

আমি মন্তব্য যতটা সম্ভব লাগাতে চেষ্টা করেছি, কিন্তু এখানেও বিবরণ: আমি ব্যবহার _ ()প্রসাধক হিসাবে ফাংশন, এক আমি প্রতি ফাংশন ঘোষণার পর করা: foo () { _। এই ফাংশনটি সঠিক ইনডেন্টেশন সহ ফাংশনটির নাম মুদ্রণ করে, অন্যান্য ফাংশনে কতটা গভীর ফাংশন নির্ভর করে (একটি ডিফল্ট ইনডেন্টেশন হিসাবে আমি স্পেসের সংখ্যা 4 ব্যবহার করি)। আমি এটিকে স্বাভাবিক মুদ্রণ থেকে পৃথক করতে ধূসর রঙে মুদ্রণ করি separate যদি ফাংশনটি আর্গুমেন্টগুলির সাথে সজ্জিত করা প্রয়োজন হয় বা তার বাইরে থাকে তবে কোনও সজ্জা ফাংশনে প্রাক-শেষ লাইনটি সংশোধন করতে পারে।

ফাংশনের ভিতরে কিছু মুদ্রণের জন্য, আমি এমন print ()ফাংশন প্রবর্তন করেছি যা এতে প্রেরণ করা সমস্ত কিছু যথাযথ ইনডেন্ট সহ প্রিন্ট করে।

ফাংশন set_indentation_for_print_functionঠিক এর কাজটি করে যা ${FUNCNAME[@]}অ্যারে থেকে ইনডেন্টেশন গণনা করে ।

উদাহরণস্বরুপ অপশন পাস না করতে এই পদ্ধতি, কিছু সংক্রান্ত ত্রুটিগুলি হয়েছে printকরতে চান echo, যেমন -nবা -e, এবং এছাড়াও ফাংশন আয় 1, এটি সজ্জিত করা হয় না পারেন। এবং আর্গুমেন্টগুলির জন্যও, printটার্মিনাল প্রস্থের চেয়ে বেশি হয়ে গেছে , এটি স্ক্রিনে আবৃত হবে, মোড়ানো রেখার জন্য ইনডেন্টেশন কেউ দেখতে পাবে না।

এই আলংকারকগুলি ব্যবহার করার দুর্দান্ত উপায় হ'ল এ ফাইলটি উত্স করতে আলাদা আলাদা ফাইল এবং প্রতিটি নতুন স্ক্রিপ্টে রেখে দেওয়া source ~/script/hand_made_bash_functions.sh

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


0

হতে পারে http://sourceforge.net/projects/oobash/ প্রোজেক্টে ডেকোরেটর উদাহরণগুলি আপনাকে সহায়তা করতে পারে (oobash / ডক্স / উদাহরণ / সাজসজ্জা.শ)।


0

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

#!/bin/bash

function decorator {
    if [ "${FUNCNAME[0]}" != "${FUNCNAME[2]}" ] ; then
        echo "Turn stuff on"
        #shellcheck disable=2068
        ${@}
        echo "Turn stuff off"
        return 0
    fi
    return 1
}

function highly_decorated {
    echo 'Inside highly decorated, calling decorator function'
    decorator "${FUNCNAME[0]}" "${@}" && return
    echo 'Done calling decorator, do other stuff'
    echo 'other stuff'
}

echo 'Running highly decorated'
# shellcheck disable=SC2119
highly_decorated

আপনি কেন এই শেলচেক সতর্কতাগুলি অক্ষম করছেন? এগুলি সঠিক বলে মনে হচ্ছে (অবশ্যই এসসি 2068 সতর্কতা উদ্ধৃত করে স্থির করা উচিত "$@")।
ডিমো 414

0

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

my_expensive_function() {
  ...
} && bc::cache my_expensive_function

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

# Given a name and an existing function, create a new function called name that
# executes the same commands as the initial function.
bc::copy_function() {
  local function="${1:?Missing function}"
  local new_name="${2:?Missing new function name}"
  declare -F "$function" &> /dev/null || {
    echo "No such function ${function}" >&2; return 1
  }
  eval "$(printf "%s()" "$new_name"; declare -f "$function" | tail -n +2)"
}

এখানে timeসজ্জা ফাংশন ব্যবহার করে এমন একটি সাজসজ্জার সাধারণ উদাহরণ রয়েছে bc::copy_function:

time_decorator() {
  bc::copy_function "$1" "time_dec::${1}" || return
  eval "${1}() { time time_dec::${1} "'"\$@"; }'
}

ডেমো:

$ slow() { sleep 2; echo done; }

$ time_decorator slow

$ $ slow
done

real    0m2.003s
user    0m0.000s
sys     0m0.002s
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.