একটি বাশ ফাংশন যা অন্যান্য ভাষার মতো আর্গুমেন্ট নেয়?


17

এ জাতীয় সেট করার জন্য আমার একটি বাশ ফাংশন রয়েছে $PATH-

assign-path()
{
    str=$1
    # if the $PATH is empty, assign it directly.
    if [ -z $PATH ]; then
        PATH=$str;
    # if the $PATH does not contain the substring, append it with ':'.
    elif [[ $PATH != *$str* ]]; then
        PATH=$PATH:$str;
    fi
}

তবে সমস্যাটি হ'ল, আমাকে বিভিন্ন ভেরিয়েবলের জন্য আলাদা আলাদা ফাংশন লিখতে হবে (উদাহরণস্বরূপ, $CLASSPATHপছন্দ মতো অন্য একটি ফাংশন assign-classpath())। আমি ব্যাশ ফাংশনে যুক্তি দেওয়ার কোনও উপায় খুঁজে পাইনি যাতে উল্লেখ করে আমি এটি অ্যাক্সেস করতে পারি।

আমার মতো কিছু থাকলে ভাল হত -

assign( bigstr, substr )
{
    if [ -z bigstr ]; then
        bigstr=substr;
    elif [[ bigstr != *str* ]]; then
        bigstr=bigstr:substr;
    fi
}

কোন ধারণা, বাশ উপরের মত কিছু অর্জন কিভাবে?


কি "অন্যান্য ভাষা"?
চোরোবা

ঠিক আছে, আমি বোঝানোর চেষ্টা করেছি যে বাশ সি / জাভা ইত্যাদির মতো "রেফারেন্স দিয়ে পাস" করতে দেয়
রামগুরুর

1
assign-path /abcযোগ করা হবে না /abcপথে $ PATH- ইতিমধ্যে থাকে /abc/def, /abcd, /def/abcইত্যাদি বিশেষ করে যদি আপনি যোগ করতে পারবেন না /binপাথ ইতিমধ্যে থাকে /usr/bin
ચમત્કાર 173

@ miracle173 - এই সত্য, কি আপনাকে যা করতে হবে বিভক্ত করা $PATHএবং মত আপনার আর্গুমেন্ট বিরুদ্ধে অস্বীকার পরীক্ষা: add=/bin dir=/usr/bin ; [ -z "${dir%"$add"}" ] || dir="${dir}:${add}"আমার উত্তরে আমি এটি যতটা যুক্তি দিয়ে আপনি কেবল পছন্দ করতে চান তা এইভাবে করি IFS=:
মাইকজারভ

কোলন-বিচ্ছিন্ন তালিকায় মান যুক্ত করার নির্দিষ্ট (উদাহরণ) ইস্যু সম্পর্কিত: আমি কীভাবে পরিষ্কারভাবে যুক্ত করতে  $PATHপারি?  এবং ডিরেক্টরিটি $PATHইতিমধ্যে সেখানে না থাকলে এটি যুক্ত করুন ( সুপার ব্যবহারকারীতে )।
স্কট

উত্তর:


17

ইন bashআপনি ব্যবহার করতে পারেন ${!varname}পরিবর্তনশীল অন্য বিষয়বস্তু দ্বারা সমর্থিত প্রসারিত করতে। উদাহরণ:

$ var=hello
$ foo () { echo "${!1}"; }
$ foo var
hello

ম্যান পৃষ্ঠা থেকে:

${!prefix*}
${!prefix@}
       Names matching prefix.  Expands to the names of variables whose names
       begin with prefix, separated by the first character of the IFS special
       variable.  When @ is used  and the expansion appears within double quotes,
       each variable name expands to a separate word.

এছাড়াও, বিষয়বস্তু দ্বারা (কোনও বিপদ ছাড়াই eval) উল্লেখযোগ্য একটি ভেরিয়েবল সেট করতে, আপনি এটি ব্যবহার করতে পারেন declare। উদাহরণ:

$ var=target
$ declare "$var=hello"
$ echo "$target"
hello

সুতরাং, আপনি আপনার ফাংশনটি এভাবে লিখতে পারেন (যত্ন নিন কারণ আপনি declareযদি কোনও ফাংশন ব্যবহার করেন তবে আপনাকে অবশ্যই দিতে হবে -gবা ভেরিয়েবলটি স্থানীয় হবে):

shopt -s extglob

assign()
{
  target=$1
  bigstr=${!1}
  substr=$2

  if [ -z "$bigstr" ]; then
    declare -g -- "$target=$substr"
  elif [[ $bigstr != @(|*:)$substr@(|:*) ]]; then
    declare -g -- "$target=$bigstr:$substr"
  fi
}

এবং এটি ব্যবহার করুন:

assign PATH /path/to/binaries

মনে রাখবেন যে আমি substrএকটি বাগও সংশোধন করেছি যেখানে ইতিমধ্যে যদি কোনও কোলনের বিচ্ছিন্ন সদস্যের একটি স্ট্রাস্টিং থাকে bigstrতবে তার নিজস্ব সদস্য না হয় তবে এটি যুক্ত করা হবে না। উদাহরণস্বরূপ, এটি ইতিমধ্যে ধারণ করে /binএকটি PATHভেরিয়েবল যুক্ত করার অনুমতি দেয় /usr/bin। এটি extglobস্ট্রিংয়ের শুরু / শেষের সাথে বা কোলনের সাথে অন্য কোনও কিছু মিলানোর জন্য সেটগুলি ব্যবহার করে । ছাড়া extglob, বিকল্পটি হ'ল :

[[ $bigstr != $substr && $bigstr != *:$substr &&
   $bigstr != $substr:* && $bigstr != *:$substr:* ]]

-gইন declareবাশের পুরানো সংস্করণে উপলভ্য নয়, এমন কোনও উপায় আছে যাতে আমি এই পশ্চাদপটে সামঞ্জস্য করতে পারি?
রামগুরুর

2
@ramgorur, আপনি exportএটি আপনার পরিবেশে (গুরুত্বপূর্ণ কিছু ওভাররাইট করার ঝুঁকিতে) বা eval(আপনি যদি সতর্ক না হন তবে সুরক্ষা সহ বিভিন্ন সমস্যা) ব্যবহার করতে পারেন। তাহলে ব্যবহার evalআপনি উচিত ঠিক হতে তোমার মত এটা করতে যদি eval "$target=\$substr"। আপনি ভুলে গিয়ে থাকেন তবে \ যদিও, এটা সম্ভাব্য কমান্ড চালানো হবে বিষয়বস্তু মধ্যে ব্যবধান আছে তা যদি substr
গ্রীম

9

ব্যাশ 4.3 এ নতুন হল -nবিকল্প declare& local:

func() {
    local -n ref="$1"
    ref="hello, world"
}

var='goodbye world'
func var
echo "$var"

প্রিন্ট আউট hello, world


বাশে নেমরেফগুলির সাথে একমাত্র সমস্যা হ'ল আপনার নামরেফ থাকতে পারে না (উদাহরণস্বরূপ কোনও ফাংশনে) নামেরফের মতো একই নামের একটি ভেরিয়েবল (ফাংশনের বাইরে) উল্লেখ করে। এটি 4.5 মুক্তির জন্য স্থির থাকতে পারে যদিও।
কুসালানন্দ

2

আপনি evalএকটি পরামিতি সেট করতে ব্যবহার করতে পারেন । এই আদেশের বিবরণ এখানে পাওয়া যাবে । নিম্নলিখিত ব্যবহার evalভুল:

ভুল () {
  eval $ 1 = $ 2
}

অতিরিক্ত মূল্যায়নের evalক্ষেত্রে আপনার ব্যবহার করা উচিত

বরাদ্দ () {
  eval $ 1 = '$ 2'
}

এই ফাংশনগুলি ব্যবহারের ফলাফলগুলি পরীক্ষা করুন:

$ এক্স 1 = '$ এক্স 2'
$ এক্স 2 = '$ এক্স 3'
$ এক্স 3 = 'এক্সএক্সএক্সএক্স'
$ 
cho প্রতিধ্বনি: $ এক্স 1:
: $ X2 তে:
cho প্রতিধ্বনি: $ এক্স 2:
: $ X3:
cho প্রতিধ্বনি: 3 এক্স 3:
: XXX:
$ 
$ ভুল Y $ X1
$ প্রতিধ্বনি: $ Y:
: $ X3:
$ 
Y Y $ X1 নির্ধারণ করুন
$ প্রতিধ্বনি: $ Y:
: $ X2 তে:
$ 
Y ওয়াই "হলো ওয়ার্ল্ড" অর্পণ করুন
$ প্রতিধ্বনি: $ Y:
: হলোর বিশ্ব:
$ # নিম্নলিখিতটি অপ্রত্যাশিত হতে পারে
Z জেড $ ওয়াই নিয়োগ করুন
$ প্রতিধ্বনি ": $ জেড:"
: আরে:
$ # সুতরাং আপনাকে যদি দ্বিতীয় তর্কটি যদি কোনও পরিবর্তনশীল হয় তবে উদ্ধৃতি দিতে হবে
Z জেড "$ ওয়াই" নিয়োগ করুন
$ প্রতিধ্বনি ": $ জেড:"
: হলোর বিশ্ব:

তবে আপনি ব্যবহার না করেই আপনার লক্ষ্য অর্জন করতে পারেন eval। আমি আরও সহজ যে এইভাবে পছন্দ।

নিম্নলিখিত ফাংশনটি সঠিক উপায়ে প্রতিস্থাপন করে (আশা করি)

বৃদ্ধি () {
  স্থানীয় বর্তমান = $ 1
  স্থানীয় এজেন্ট = $ 2
  স্থানীয় নতুন
  যদি [[-z $ CURRENT]]; তারপর
    নতুন = $ বৃদ্ধি
  এলিফ [[! ((UR বর্তমান = $ আগস্ট) || (UR বর্তমান = G আগস্ট: *) || \
    (UR বর্তমান = =: $ আগস্ট) || (UR বর্তমান = =: $ আগস্ট: *))]]; তারপর
    নতুন = $ বর্তমান: $ বৃদ্ধি
  আর
    নতুন $ বর্তমান =
    ফাই
  প্রতিধ্বনি "$ নতুন"
}

নিম্নলিখিত আউটপুট চেক করুন

বর্ধিত / usr / বিন / বিন
, / Usr / বিন: / বিন

বর্ধন / usr / বিন: / বিন / বিন
, / Usr / বিন: / বিন

অগ্রগতি / usr / বিন: / বিন: / usr / স্থানীয় / বিন / বিন
, / Usr / বিন: / বিন / usr / স্থানীয় / বিন

বৃদ্ধি / বিন: / usr / বিন / বিন
/ বিন / usr / বিন

বর্ধন / বিন / বিন
/ বিন


বৃদ্ধি / usr / বিন: / বিন
, / Usr / বিন :: / বিন

বৃদ্ধি / usr / বিন: / বিন: / বিন
, / Usr / বিন: / বিন:

অগ্রগতি / usr / বিন: / বিন: / usr / স্থানীয় / বিন: / বিন
, / Usr / বিন: / বিন / usr / স্থানীয় / বিন:

বৃদ্ধি / বিন: / usr / বিন: / বিন
/ বিন / usr / বিন:

বর্ধন / বিন: / বিন
/ বিন:


বৃদ্ধি: / বিন
:: / বিন


বর্ধন "/ usr lib" "/ usr বিন"
/ usr lib: / usr বিন

বর্ধন "/ usr lib: / usr বিন" "/ usr বিন"
/ usr lib: / usr বিন

augmentভেরিয়েবল সেট করতে এখন আপনি নিম্নলিখিত পদ্ধতিতে ফাংশনটি ব্যবহার করতে পারেন :

PATH = ug বৃদ্ধি PATH / bin` `
CLASSPATH = ug CLASSPATH / bin` বৃদ্ধি `
LD_LIBRARY_PATH = ug বৃদ্ধি এলডি_লিবারি_প্যাথ / ইউএসআর / লাইব`

এমনকি আপনার স্পষ্ট বিবৃতি ভুল wrong এটি উদাহরণস্বরূপ: v='echo "OHNO!" ; var' ; l=val ; eval $v='$l' - ভার নির্ধারণের আগে "ওএনওও প্রতিধ্বনিত হবে You =।
মাইকসার্ভ

@ মিকসার্ভ আপনার মন্তব্যের জন্য আপনাকে ধন্যবাদ জানায় তবে আমি মনে করি এটি একটি বৈধ উদাহরণ নয়। অ্যাসাইন্ট স্ক্রিপ্টের প্রথম আর্গুমেন্টটি একটি ভেরিয়েবলের নাম বা একটি ভেরিয়েবল হওয়া উচিত যা একটি ভেরিয়েবল নাম ধারণ করে যা =এসাইনগমেন্ট স্টেটমেন্টের বাম পাশে ব্যবহৃত হয় । আপনি তর্ক করতে পারেন যে আমার স্ক্রিপ্ট এর তর্কটি পরীক্ষা করে না। ঐটা সত্য. এমনকি কোনও তর্ক আছে কিনা বা আর্গুমেন্টের সংখ্যাটি বৈধ কিনা তাও আমি চেক করি না। কিন্তু এটি ছিল উদ্দেশ্য দ্বারা। ওপি চাইলে এ জাতীয় চেক যুক্ত করতে পারে।
ચમત્કાર173

@ মিকসার্ভ: আমি মনে করি যে প্রথম যুক্তিটি নিঃশব্দে একটি বৈধ ভেরিয়েবল নামে রূপান্তর করার প্রস্তাবটি ভাল ধারণা নয়: 1) কিছু ভেরিয়েবল সেট / ওভাররাইট করা হয়েছে যা ব্যবহারকারীর দ্বারা উদ্দিষ্ট নয়। 2) ত্রুটিটি ফাংশনের ব্যবহারকারীর কাছ থেকে লুকানো আছে। এটি কখনই ভাল ধারণা নয়। যদি এটি ঘটে তবে কেবল একটি ত্রুটি উত্থাপন করা উচিত।
ચમત્કાર173

@ মাইকজার্ভ: এটি আকর্ষণীয় যখন কেউ আপনার ভেরিয়েবল v(এর মান আরও ভাল) ব্যবহারের ক্রিয়াটির দ্বিতীয় যুক্তি হিসাবে ব্যবহার করতে চায় । সুতরাং এর মান একটি অনুকরণের ডানদিকে থাকা উচিত। ফাংশনের যুক্তিটি উদ্ধৃত করা জরুরী assign। আমি আমার পোস্টে এই সূক্ষ্মতা যুক্ত করেছি।
ચમત્કાર173

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

2

কয়েকটি কৌশল দ্বারা আপনি অ্যারে (ব্যাশ 3 এবং 4 এ পরীক্ষিত) সহ কার্যত নামকরণের পরামিতিগুলি ফাংশনে পাস করতে পারেন।

আমি যে পদ্ধতিটি বিকাশ করেছি তা আপনাকে এরকম কোনও ফাংশনে পাস করা প্যারামিটারগুলি অ্যাক্সেস করতে দেয়:

testPassingParams() {

    @var hello
    l=4 @array anArrayWithFourElements
    l=2 @array anotherArrayWithTwo
    @var anotherSingle
    @reference table   # references only work in bash >=4.3
    @params anArrayOfVariedSize

    test "$hello" = "$1" && echo correct
    #
    test "${anArrayWithFourElements[0]}" = "$2" && echo correct
    test "${anArrayWithFourElements[1]}" = "$3" && echo correct
    test "${anArrayWithFourElements[2]}" = "$4" && echo correct
    # etc...
    #
    test "${anotherArrayWithTwo[0]}" = "$6" && echo correct
    test "${anotherArrayWithTwo[1]}" = "$7" && echo correct
    #
    test "$anotherSingle" = "$8" && echo correct
    #
    test "${table[test]}" = "works"
    table[inside]="adding a new value"
    #
    # I'm using * just in this example:
    test "${anArrayOfVariedSize[*]}" = "${*:10}" && echo correct
}

fourElements=( a1 a2 "a3 with spaces" a4 )
twoElements=( b1 b2 )
declare -A assocArray
assocArray[test]="works"

testPassingParams "first" "${fourElements[@]}" "${twoElements[@]}" "single with spaces" assocArray "and more... " "even more..."

test "${assocArray[inside]}" = "adding a new value"

অন্য কথায়, কেবলমাত্র আপনি নিজের প্যারামিটারগুলিকে তাদের নামে কল করতে পারবেন না (যা আরও বেশি পাঠযোগ্য কোর তৈরি করে) আপনি আসলে অ্যারেগুলি পাস করতে পারেন (এবং ভেরিয়েবলের উল্লেখ - এই বৈশিষ্ট্যটি যদিও কেবল বাশ ৪.৩ এ কাজ করে)! এছাড়াও, ম্যাপযুক্ত ভেরিয়েবলগুলি সমস্ত স্থানীয় স্কোপে যেমন ঠিক $ 1 (এবং অন্যান্য)।

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

Function.AssignParamLocally() {
    local commandWithArgs=( $1 )
    local command="${commandWithArgs[0]}"

    shift

    if [[ "$command" == "trap" || "$command" == "l="* || "$command" == "_type="* ]]
    then
        paramNo+=-1
        return 0
    fi

    if [[ "$command" != "local" ]]
    then
        assignNormalCodeStarted=true
    fi

    local varDeclaration="${commandWithArgs[1]}"
    if [[ $varDeclaration == '-n' ]]
    then
        varDeclaration="${commandWithArgs[2]}"
    fi
    local varName="${varDeclaration%%=*}"

    # var value is only important if making an object later on from it
    local varValue="${varDeclaration#*=}"

    if [[ ! -z $assignVarType ]]
    then
        local previousParamNo=$(expr $paramNo - 1)

        if [[ "$assignVarType" == "array" ]]
        then
            # passing array:
            execute="$assignVarName=( \"\${@:$previousParamNo:$assignArrLength}\" )"
            eval "$execute"
            paramNo+=$(expr $assignArrLength - 1)

            unset assignArrLength
        elif [[ "$assignVarType" == "params" ]]
        then
            execute="$assignVarName=( \"\${@:$previousParamNo}\" )"
            eval "$execute"
        elif [[ "$assignVarType" == "reference" ]]
        then
            execute="$assignVarName=\"\$$previousParamNo\""
            eval "$execute"
        elif [[ ! -z "${!previousParamNo}" ]]
        then
            execute="$assignVarName=\"\$$previousParamNo\""
            eval "$execute"
        fi
    fi

    assignVarType="$__capture_type"
    assignVarName="$varName"
    assignArrLength="$__capture_arrLength"
}

Function.CaptureParams() {
    __capture_type="$_type"
    __capture_arrLength="$l"
}

alias @trapAssign='Function.CaptureParams; trap "declare -i \"paramNo+=1\"; Function.AssignParamLocally \"\$BASH_COMMAND\" \"\$@\"; [[ \$assignNormalCodeStarted = true ]] && trap - DEBUG && unset assignVarType && unset assignVarName && unset assignNormalCodeStarted && unset paramNo" DEBUG; '
alias @param='@trapAssign local'
alias @reference='_type=reference @trapAssign local -n'
alias @var='_type=var @param'
alias @params='_type=params @param'
alias @array='_type=array @param'

1
assign () 
{ 
    if [ -z ${!1} ]; then
        eval $1=$2
    else
        if [[ ${!1} != *$2* ]]; then
            eval $1=${!1}:$2
        fi
    fi
}

$ echo =$x=
==
$ assign x y
$ echo =$x=
=y=
$ assign x y
$ echo =$x=
=y=
$ assign x z
$ echo =$x=
=y:z=

এই ফিট করে?


হাই, আমি এটি আপনার মতো করার চেষ্টা করেছি, কিন্তু কাজ করছি না, নবাগত হওয়ার জন্য দুঃখিত sorry আপনি কি আমাকে বলতে পারেন যে এই স্ক্রিপ্টটিতে কী ভুল ?
রামগুরুর

1
আপনার ব্যবহার evalস্বেচ্ছাচারিত কমান্ড প্রয়োগের জন্য সংবেদনশীল।
ক্রিস ডাউন

ঝে evalলাইনগুলিকে নিরাপদ করার জন্য আপনার ধারণা আছে ? সাধারণত, যখন আমি মনে করি যে আমার স্পষ্ট প্রয়োজন, তখন আমি সিদ্ধান্ত নেব * sh ব্যবহার না করে পরিবর্তে কোনও ভিন্ন ভাষায় স্যুইচ করুন। অন্যদিকে, কিছু PATH- এর মতো ভেরিয়েবলগুলিতে এন্ট্রি সংযোজন করতে স্ক্রিপ্টগুলিতে এটি ব্যবহার করে এটি স্ট্রিং ধ্রুবক দিয়ে চলবে এবং ব্যবহারকারীর ইনপুট নয় ...

1
আপনি evalনিরাপদে করতে পারেন - তবে এটি অনেক চিন্তাভাবনা করে। আপনি শুধু একটি প্যারামিটার উল্লেখ করার চেষ্টা করছেন, তাহলে আপনি ভালো কিছু করতে চাই চাই: eval "$1=\"\$2\""উপর যে ভাবে eval'sপ্রথম পাস এটি শুধুমাত্র $ 1 মূল্যায়ণ এবং দ্বিতীয় তে এটি মান = "$ 2" আছে। তবে আপনাকে অন্য কিছু করতে হবে - এটি এখানে অপ্রয়োজনীয়।
মাইকজার্ভ

আসলে, আমার উপরের মন্তব্যটিও ভুল। আপনার করতে হবে "${1##*[;"$IFS"]}=\"\$2\""- এবং এটি কোনও ওয়্যারেন্টি সহ আসে না। বা eval "$(set -- $1 ; shift $(($#-1)) ; echo $1)=\"\$2\""। এটা সহজ না.
মাইকজার্ভ

1

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

আপনি pythonযদি একেবারেই সম্ভব হয় তবে কোনও আলাদা শেল স্ক্রিপ্ট (যেমন বা কিছু) সম্পূর্ণরূপে দেখার চেয়ে আপনি সম্ভবত আরও ভাল । যদি আপনি কোনও ভাষার সীমাবদ্ধতার বিরুদ্ধে চলে যান তবে আপনাকে একটি নতুন ভাষা ব্যবহার করা শুরু করতে হবে।


bashজীবনের প্রথম দিকে এটি সত্য ছিল। তবে এখন নির্দিষ্ট বিধান করা হয়েছে। সম্পূর্ণ রেফারেন্স ভেরিয়েবলগুলি এখন উপলব্ধbash 4.3 - ডারোবার্টের উত্তর দেখুন
গ্রেম

এবং আপনি যদি এখানে তাকান, আপনি দেখতে পাবেন যে আপনি কেবল পসিএক্স
মাইকজারভ

1

স্ট্যান্ডার্ড shসিনট্যাক্সের সাথে (কেবল এতেই কাজ করবে bash, এবং নাও bash), আপনি এটি করতে পারেন:

assign() {
  eval '
    case :${'"$1"'}: in
      (::) '"$1"'=$2;;   # was empty, copy
      (*:"$2":*) ;;      # already there, do nothing
      (*) '"$1"'=$1:$2;; # otherwise, append with a :
    esac'
}

ব্যবহারের সমাধানের জন্য মতো bash'র declare, এটা নিরাপদ যতদিন $1একটি বৈধ পরিবর্তনশীল নাম ধারণ করে।


0

নাম প্রকাশিত তর্কগুলিতে:

এটি খুব সহজভাবে সম্পন্ন হয়েছে এবং bashএটি মোটেই প্রয়োজন হয় না - এটি প্যারামিটারের বিস্তারের মাধ্যমে অ্যাসাইনমেন্টের প্রাথমিক POSIX নির্দিষ্ট আচরণ:

: ${PATH:=this is only assigned to \$PATH if \$PATH is null or unset}

@ গ্র্যামের কাছে অনুরূপ শিরাতে ডেমো করতে, তবে একটি বহনযোগ্য উপায়ে:

_fn() { echo "$1 ${2:-"$1"} $str" ; }

% str= ; _fn "${str:=hello}"
> hello hello hello

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

সমাধান:

আপনার নির্দিষ্ট সমস্যার জন্য, আমি বিশ্বাস করি না যে নামযুক্ত যুক্তিগুলি প্রয়োজনীয়, যদিও তারা অবশ্যই সম্ভব're $IFSপরিবর্তে ব্যবহার করুন:

assign() { oFS=$IFS ; IFS=: ; add=$* 
    set -- $PATH ; for p in $add ; do { 
        for d ; do [ -z "${d%"$p"}" ] && break 
        done ; } || set -- $* $p ; done
    PATH= ; echo "${PATH:="$*"}" ; IFS=$oFS
}

এটি চালানোর সময় আমি যা পাই তা এখানে:

% PATH=/usr/bin:/usr/yes/bin
% assign \
    /usr/bin \
    /usr/yes/bin \
    /usr/nope/bin \
    /usr/bin \
    /nope/usr/bin \
    /usr/nope/bin

> /usr/bin:/usr/yes/bin:/usr/nope/bin:/nope/usr/bin

% echo "$PATH"
> /usr/bin:/usr/yes/bin:/usr/nope/bin:/nope/usr/bin

% dir="/some crazy/dir"
% p=`assign /usr/bin /usr/bin/new "$dir"`
% echo "$p" ; echo "$PATH"
> /usr/bin:/usr/yes/bin:/usr/nope/bin:/nope/usr/bin:/some crazy/dir:/usr/bin/new
> /usr/bin:/usr/yes/bin:/usr/nope/bin:/nope/usr/bin:/some crazy/dir:/usr/bin/new

লক্ষ্য করুন এটি কেবল যুক্তি যুক্ত করেছে যা ইতিমধ্যে ছিল না $PATHবা এর আগে এসেছিল? বা এমনকি এটি মোটেও একাধিক যুক্তি নিয়েছিল? $IFSসুবিধাজনক


হাই, আমি অনুসরণ করতে ব্যর্থ, তাই আপনি দয়া করে এটি আরও কিছুটা বিস্তারিত বলতে পারেন? ধন্যবাদ।
রামগুরুর

আমি ইতিমধ্যে এটি করছি ... আরও কয়েক মুহুর্ত দয়া করে ...
মাইক্রজারভ

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

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

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

-2

আমি রুবি, পাইথন ইত্যাদির মতো কিছু পাই না তবে এটি আমার কাছে অনুভব করে feels

foo() {
  BAR="$1"; BAZ="$2"; QUUX="$3"; CORGE="$4"
  ...
}

আমার মতামত অনুসারে পাঠযোগ্যতা আরও ভাল, আপনার পরামিতিগুলির নাম ঘোষণার জন্য 4 টি লাইন অতিরিক্ত। পাশাপাশি আধুনিক ভাষাগুলির কাছাকাছি দেখায়।


(1) প্রশ্নটি শেল ফাংশন সম্পর্কে। আপনার উত্তরটি একটি কঙ্কালের শেল ফাংশন উপস্থাপন করে। এর বাইরে আপনার প্রশ্নের উত্তরটির কোনও যোগসূত্র নেই। (২) আপনি ভাবেন যে পৃথক রেখাগুলি নেওয়া এবং সেগুলি পৃথক পৃথক পৃথক পৃথক রেখার সাথে একত্রে যুক্ত করা পাঠযোগ্যতা বৃদ্ধি করে ? আমি বিশ্বাস করি আপনি এটি পেছনের দিকে পেয়েছেন; আপনার এক-লাইনের শৈলীটি  মাল্টি-লাইন শৈলীর চেয়ে কম পঠনযোগ্য।
স্কট

অপ্রয়োজনীয় অংশ হ্রাস যদি বিন্দু হয়, তবে কোটস এবং সেমিকোলন কেন? a=$1 b=$2 ...ঠিক পাশাপাশি কাজ করে।
ইলকচাচু
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.