বাশ [[]] কমান্ডের ভিতরে স্বয়ংক্রিয় পরিবর্তনশীল প্রসারণ


13

কোনও ভেরিয়েবলকে ডিফারেন্স করার সময় bashআপনাকে $সাইন ব্যবহার করতে হবে। তবুও, মনে হচ্ছে যে নিম্নলিখিতটি ঠিক কাজ করছে:

x=5
[[ x -gt 2 ]]

কেউ কি এই ব্যাখ্যা করতে পারেন?

সম্পাদনা করুন: (আরও তথ্য)

আমার অর্থ হ'ল কীভাবে এবং কেন [[]] কমান্ডটি vari চিহ্ন ব্যতীত আমার পরিবর্তনশীল এক্সকে ডিফারেন্স করছে। এবং হ্যাঁ, যদি x = 1 হয় তবে বিবৃতিটি মিথ্যা হিসাবে মূল্যায়ন করা হবে (রিটার্নের স্ট্যাটাস 1)


2
"ঠিকঠাক কাজ" বলতে কী বোঝ? এবং যদি আপনি x=1অনুসরণ করেন তবে আপনার মূল্যায়ন কি পরিবর্তন হয় [[ x -gt 2]]?
nohillside

আমার অর্থ: কীভাবে এবং কেন [[]] কমান্ডটি vari চিহ্ন ব্যতীত আমার পরিবর্তনশীল এক্সকে ডিফারেন্স করছে। এবং হ্যাঁ, x = 1 হলে, বিবৃতিটি মিথ্যা (প্রত্যাবর্তন স্থিতি 1)
অতিথি

উত্তর:


9

কারণ হ'ল -eqযুক্তিগুলির একটি গাণিতিক মূল্যায়ন জোর করে।

একটি গাণিতিক অপারেটর: -eq, -gt, -lt, -ge, -leএবং -neএকটি ভিতরে [[ ]](ksh এ, zsh এবং ব্যাশ) স্বয়ংক্রিয়ভাবে সি ল্যাঙ্গুয়েজ হিসেবে পরিবর্তনশীল নামের প্রসারিত করতে মানে, একটি নেতৃস্থানীয় জন্য প্রয়োজন হবে না $

  • নিশ্চিতকরণের জন্য আমাদের অবশ্যই বাশ সোর্স কোডটি সন্ধান করতে হবে। ম্যানুয়ালটি কোনও সরাসরি নিশ্চিতকরণ সরবরাহ করে না।

    test.cগাণিতিক অপারেটরগুলির প্রসেসিংয়ের ভিতরে এই ফাংশনটি পড়ে:

    arithcomp (s, t, op, flags)

    যেখানে sএবং tউভয় অপারেশন হয়। অপারেশনগুলি এই ফাংশনে হস্তান্তরিত হয়:

    l = evalexp (s, &expok);
    r = evalexp (t, &expok);

    ফাংশনটি evalexpভিতরে সংজ্ঞায়িত করা হয়েছে expr.c, যার এই শিরোনামটি রয়েছে:

    /* expr.c -- arithmetic expression evaluation. */

    সুতরাং, হ্যাঁ, একটি গাণিতিক অপারেটরের উভয় পক্ষই (সরাসরি) পাটিগণিতের এক্সপ্রেশন মূল্যায়নের মধ্যে পড়ে। সরাসরি, কোনও বুট নেই, কোনও আইএফএস নেই।


অনুশীলনে, সাথে:

 $ x=3

এই উভয়ই ব্যর্থ:

 $ [[ x = 4 ]] && echo yes || echo no
 no

 $ [[ x = 3 ]] && echo yes || echo no
 no

যা সঠিক, xপ্রসারিত xহচ্ছে না এবং সংখ্যার সমান নয়।

যাহোক:

 $ [[ x -eq 3 ]] && echo yes || echo no
 yes

 $ [[ x -eq 4 ]] && echo yes || echo no
 no

নামের ভেরিয়েবল xপ্রসারিত হয় (এমনকি a ছাড়াই)।

এটি […]zsh বা bash এর জন্য ঘটে না (এটি ksh এ হয়)।


এটি একটির ভিতরে যা ঘটে তার সাথে একই $((…)):

 $ echo $(( x + 7 ))
 10

এবং, দয়া করে বুঝতে পারেন যে এটি (খুব) পুনরাবৃত্তি (ড্যাশ এবং যশ ব্যতীত):

 $ a=b b=c c=d d=e e=f f=3
 $ echo "$(( a + 7 ))" 
 10

এবং বেশ ঝুঁকিপূর্ণ:

 $ x='a[$(date -u)]'
 $ [[ x -eq 3 ]] && echo yes || echo no
 bash: Tue Dec  3 23:18:19 UTC 2018: syntax error in expression (error token is "Dec  3 23:18:19 UTC 2018")

সিনট্যাক্স ত্রুটি সহজেই এড়ানো যায়:

 $ a=3; x='a[$(date -u >/dev/tty; echo 0)]'

 $ [[ x -eq 3 ]] && echo yes || echo no
 Tue Dec  4 09:02:06 UTC 2018
 yes

প্রবাদটি যেমন রয়েছে: আপনার ইনপুটটি স্যানিটাইজ করুন

 $ [[ ${x//[^0-9]} -eq 3 ]] && echo yes || echo no
 no

😮 এর শেষ


(পুরানো) বাহ্যিক /usr/bin/test(বিল্টিন নয় test) এবং এখনও পুরানো এবং বাহ্যিক উভয়ই কেবলমাত্র পূর্ণসংখ্যার (এবং দৃশ্যত, কেবলমাত্র দশমিক পূর্ণসংখ্যার) এক্সপ্রেশনকেexpr প্রসারিত করে না :

 $ /usr/bin/test "x" -eq 3
 /usr/bin/test: invalid integer x

 $ expr x + 3
 expr: non-integer argument

মজাদার. এটি কীভাবে সম্ভব তা বলা শক্ত নয় - [[কীওয়ার্ড হওয়ায় কমান্ডটি পড়ার পরে অপারেটর এবং অপারেটরগুলি সনাক্ত করা হয় এবং প্রসারিত হওয়ার পরে নয়। সুতরাং , বলার চেয়ে আরও স্মার্ট উপায়ে [[চিকিত্সা করতে পারে । তবে আমি যা অবাক করি তা হল: যৌগিক আদেশগুলি ব্যাখ্যা করতে লজিক ব্যাশের ব্যবহার সম্পর্কে আমরা কোথায় ডকুমেন্টেশন পেতে পারি? এটি আমার কাছে একেবারে সুস্পষ্ট বলে মনে হচ্ছে না এবং আমি স্পষ্টতই বা এর মধ্যে সন্তোষজনক ব্যাখ্যা খুঁজে পেতে পারছি না । -eq[maninfo bash
ফ্রে-সান

বাশ এটি কোথাও খুঁজে পাবে এটি নথিভুক্ত করে না। Man ksh93 এ এক ধরণের বর্ণনা রয়েছে : নিম্নলিখিত অপ্রচলিত গাণিতিক তুলনাগুলিও অনুমোদিত: exp1 -eq exp2 । সেখানে এই লেখা মানুষ zshbuiltins বিভাগে গাণিতিক অপারেটর বরং গাণিতিক এক্সপ্রেশন চেয়ে আর্গুমেন্ট পূর্ণসংখ্যা আশা । যা নিশ্চিত করে যে কিছু আর্গুমেন্ট এই উদ্ধৃতিতে উল্লিখিত নয় এমন শর্তের অধীনে পরীক্ষা বিল্টিন দ্বারা গাণিতিক এক্সপ্রেশন হিসাবে বিবেচিত হবে। আমি উত্স কোডটি দিয়ে নিশ্চিত করব…।…test
নোটঅনিক্সনাজি

7

সংখ্যাসূচক তুলনা operands -eq, -gt, -lt, -ge, -leএবং -neগাণিতিক এক্সপ্রেশন হিসাবে নেয়া হয়। কিছু সীমাবদ্ধতার সাথে, তাদের এখনও একক শেল শব্দ হওয়া দরকার।

পাটিগণিতের বহিঃপ্রকাশে পরিবর্তনশীল নামের আচরণটি শেল অ্যারিমেটমিকতে বর্ণিত :

শেল ভেরিয়েবল অপারেন্ডস হিসাবে অনুমোদিত; অভিব্যক্তিটি মূল্যায়নের আগে প্যারামিটার সম্প্রসারণ করা হয়। একটি অভিব্যক্তির মধ্যে, শেল ভেরিয়েবলগুলি পরামিতি প্রসারণ সিনট্যাক্স ব্যবহার না করে নাম দ্বারাও উল্লেখ করা যেতে পারে। প্যারামিটার এক্সপেনশন সিনট্যাক্স ব্যবহার না করে নাম দ্বারা রেফারেন্স করা হলে শেল পরিবর্তনশীল যা নাল বা আনসেট হয় 0 এ মূল্যায়ন করে।

এবং যদিও:

কোনও ভেরিয়েবলের মান উল্লেখ করা হয় যখন এটি গাণিতিক এক্সপ্রেশন হিসাবে উল্লেখ করা হয়

তবে আমি আসলে ডকুমেন্টেশনের অংশটি খুঁজে পাই না যেখানে বলা হয়েছে যে সংখ্যার তুলনাগুলি গাণিতিক ভাব প্রকাশ করে take এটি কন্ডিশনাল কনস্ট্রাক্টস এর অধীনে [[বর্ণিত নয় বা বাশ শর্তসাপেক্ষ এক্সপ্রেশনগুলিতে বর্ণনা করা হয়নি ।

কিন্তু, পরীক্ষার দ্বারা, এটি উপরে বলা হিসাবে কাজ করবে বলে মনে হচ্ছে।

সুতরাং, এই জাতীয় জিনিসগুলি কাজ করে:

a=6
[[ a -eq 6 ]] && echo y 
[[ 1+2+3 -eq 6 ]] && echo y
[[ "1 + 2 + 3" -eq 6 ]] && echo y

এটিও (ভেরিয়েবলের মান মূল্যায়ন করা হয়):

b='1 + 2 + 3'
[[ b -eq 6 ]] && echo y

তবে এটি হয় না; [[ .. ]]পার্স করার সময় এটি কোনও একক শেল শব্দ নয় , সুতরাং শর্তাধীন একটি বাক্য গঠন আছে:

[[ 1 + 2 + 3 -eq 6 ]] && echo y

অন্যান্য পাটিগণিত প্রসঙ্গে, সাদা অংশ ছাড়া ভাব প্রকাশের দরকার নেই। এই মুদ্রণগুলি 999, বন্ধনীগুলি সূচকগুলিতে নির্বিঘ্নে পাটিগণিতের প্রকাশকে সীমিত করে দেয়:

a[6]=999; echo ${a[1 + 2 + 3]}

অন্যদিকে, =তুলনাটি একটি প্যাটার্ন ম্যাচ , এবং এটি গাণিতিককে জড়িত করে না বা কোনও গাণিতিক প্রসঙ্গে (শর্তাধীন কনস্ট্রাক্টস) স্বয়ংক্রিয় পরিবর্তনশীল প্রসারণও জড়িত না:

যখন ==এবং !=অপারেটরদের ব্যবহার করা হয়, অপারেটর ডানদিকে স্ট্রিং, প্যাটার্ন ম্যাচিং মধ্যে নীচে বর্ণিত নিয়ম অনুযায়ী একটি প্যাটার্ন বিবেচনা করা এবং extglob শেল বিকল্প হিসাবে যদি সক্ষম হয় মিলেছে করা হয়। =অপারেটর অভিন্ন ==

সুতরাং এটি মিথ্যা কারণ স্ট্রিংগুলি স্পষ্টতই পৃথক:

[[ "1 + 2 + 3" = 6 ]] 

এটি যেমন, সংখ্যাসূচক মান একই হলেও:

[[ 6 = 06 ]] 

এবং এখানেও, স্ট্রিংগুলি ( xএবং 6) তুলনা করা হয়, সেগুলি পৃথক:

x=6
[[ x = 6 ]]

এটি চলকটি প্রসারিত করবে, তবে এটি সত্য:

x=6
[[ $x = 6 ]]

আসলে ডকুমেন্টেশনের অংশটি খুঁজে পাচ্ছেন না যেখানে বলা হয়েছে যে সংখ্যার তুলনাগুলি গাণিতিক ভাব প্রকাশ করে। নিশ্চিতকরণ হয় কোড
নোটঅনিক্সনাজি

নিকটতম বিষয়টি হ'ল বর্ণনাটি arg1 OP arg2বলছে যে আর্গগুলি ধনাত্মক বা নেতিবাচক পূর্ণসংখ্যার হতে পারে, যা আমার ধারণা অনুমান করা হয় যে তারা বোঝাচ্ছে যে তারা পাটিগণিত প্রকাশ হিসাবে বিবেচিত হচ্ছে as বিভ্রান্তিকরভাবে, এটি এও বোঝায় যে তারা শূন্য হতে পারে না। :)
বারমার

@ বারমার, আহ, ঠিক আছে। তবে এটি সংখ্যার তুলনার ক্ষেত্রেও প্রযোজ্য [এবং সেখানে সেগুলি গাণিতিক প্রকাশ নেই। পরিবর্তে, বাশ অ-পূর্ণসংখ্যা সম্পর্কে অভিযোগ করে।
ilkkachu

@ ইলক্কাচু [একটি বহিরাগত কমান্ড, এতে শেল ভেরিয়েবলের অ্যাক্সেস নেই। এটি প্রায়শই অন্তর্নির্মিত কমান্ডটি দিয়ে অনুকূলিত হয় তবে এটি এখনও একই আচরণ করে।
বর্মার

@ বারমার, আমি যেটি বোঝাতে চাইছিলাম তা হল "আরগ 1 এবং আরজি 2" ইতিবাচক বা নেতিবাচক পূর্ণসংখ্যার হতে পারে " বাশ শর্তসাপেক্ষ এক্সপ্রেশনগুলিতে উপস্থিত হয় এবং সেই তালিকাটি [ঠিক তেমন প্রযোজ্য [[। এমনকি [, ওপেনেন্ডগুলি -eqএবং বন্ধুদের কাছে ইন্টিজার হতে / হয়, সুতরাং সেই বিবরণটিও প্রযোজ্য। "অবশ্যই পূর্ণসংখ্যার হতে হবে" নেওয়া মানে গাণিতিক এক্সপ্রেশন হিসাবে ব্যাখ্যা করা হয় "উভয় ক্ষেত্রেই প্রযোজ্য না। (সম্ভবত কমপক্ষে আংশিকভাবে [কোনও সাধারণ কমান্ডের মতো অভিনয় করার কারণে , যেমনটি আপনি বলেছেন)
ilkkachu

1

হ্যাঁ, আপনার পর্যবেক্ষণটি সঠিক, ভেরিয়েবল প্রসারণটি ডাবল বন্ধনীগুলির অধীনে এক্সপ্রেশনগুলিতে সঞ্চালিত হয় [[ ]], সুতরাং আপনাকে $কোনও ভেরিয়েবল নামের সামনে রাখার দরকার নেই ।

এটি bashম্যানুয়ালটিতে স্পষ্টভাবে বলা হয়েছে :

[[অভিব্যক্তি]]

(...) শব্দ বিভাজন এবং পথের নাম প্রসারিত শব্দগুলি [[এবং]] এর মধ্যে সম্পাদিত হয় না; টিলডে এক্সপেনশন, প্যারামিটার এবং ভেরিয়েবল এক্সপেনশন, পাটিগণিতের সম্প্রসারণ, কমান্ড প্রতিস্থাপন, প্রক্রিয়া প্রতিস্থাপন এবং উদ্ধৃতি অপসারণ সম্পাদন করা হয়।

লক্ষ্য করুন যে এটি একক-বন্ধনী সংস্করণের ক্ষেত্রে নয় [ ], যেমন [শেল কীওয়ার্ড (সিনট্যাক্স) নয়, বরং একটি আদেশ (ব্যাশে এটি অন্তর্নির্মিত, অন্যান্য শেলগুলি বহিরাগত ব্যবহার করতে পারে, পরীক্ষার জন্য রেখাযুক্ত)।


1
জবাব দেওয়ার জন্য আপনাকে ধন্যবাদ। দেখে মনে হচ্ছে এটি কেবল সংখ্যার জন্য কাজ করছে। x = শহর [[$ x == শহর]] এটি $ চিহ্ন ছাড়া কাজ করে না।
অতিথি

3
দেখে মনে হচ্ছে এখানে আরও রয়েছে: (x=1; [[ $x = 1 ]]; echo $?)রিটার্ন 0, (x=1; [[ x = 1 ]]; echo $?)রিটার্ন 1, অর্থাত্ প্যারামিটার সম্প্রসারণটি xযখন আমরা স্ট্রিংয়ের তুলনা করি তখন এটি করা হয় না । এই আচরণটি পাটিগণিতের মূল্যায়নের মতো দেখা যায় যা পাটিগণিতের বিস্তারের দ্বারা চালিত হয়, অর্থাত্ যা ঘটে (x=1; echo $((x+1)))। (পাটিগণিত মূল্যায়ন সম্পর্কে, man bashবলেছেন যে "" একটি অভিব্যক্তির মধ্যে, পরামিতি প্রসারণ সিনট্যাক্স ব্যবহার না করে শেল ভেরিয়েবলগুলি নামের দ্বারাও উল্লেখ করা যেতে পারে)
ফ্রে-সান

@ ফ্রে-সান প্রকৃতপক্ষে, -gtঅপারেটরটি সংখ্যাটি প্রত্যাশা করে তাই পুরো এক্সপ্রেশনটি ভিতরে হিসাবে এমনভাবে পুনরায় মূল্যায়ন করা হয় (())অন্যদিকে ==স্ট্রিংগুলি প্রত্যাশা করে তাই পরিবর্তে প্যাটার্ন-ম্যাচিং ফাংশন ট্রিগার করে। আমি উত্স কোডটি খনন করি নি তবে যুক্তিযুক্ত বলে মনে হচ্ছে।
jimmij

[বাশে একটি শেল অন্তর্নির্মিত।
নিজাম মোহাম্মদ

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