কখন ডাবল-কোটিং দরকার?


120

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

তবে আমি বুঝতে পেরেছি যে শেলের আরও সাম্প্রতিক সংস্করণগুলিতে, ডাবল-কোটিংয়ের আর সবসময় প্রয়োজন হয় না (অন্তত উপরে বর্ণিত উদ্দেশ্যটির জন্য)। উদাহরণস্বরূপ, এতে bash:

% FOO='bar baz'
% [ $FOO = 'bar baz' ] && echo OK
bash: [: too many arguments
% [[ $FOO = 'bar baz' ]] && echo OK
OK
% touch 'bar baz'
% ls $FOO
ls: cannot access bar: No such file or directory
ls: cannot access baz: No such file or directory

ইন zsh, অপরপক্ষে, একই তিন কমান্ড সফল। অতএব, এই পরীক্ষার উপর ভিত্তি করে, এটি মনে হয় যে, bashকেউ ভিতরে ডাবল উদ্ধৃতিগুলি বাদ দিতে পারে [[ ... ]]তবে ভিতরে [ ... ]বা কমান্ড-লাইন আর্গুমেন্টে নয়, তবে zshএই সমস্ত ক্ষেত্রে ডাবল উক্তি বাদ দেওয়া যেতে পারে।

তবে উপরের মত উপাখ্যানীয় উদাহরণগুলি থেকে সাধারণ নিয়মগুলি অনুমান করা একটি সম্ভাবনার প্রস্তাব। ডাবল-কোটেশন প্রয়োজনীয় যখন এর সংক্ষিপ্তসারটি দেখতে ভাল লাগবে। আমি প্রাথমিকভাবে আগ্রহী zsh, bashএবং /bin/sh


10
Zsh এ আপনার পর্যবেক্ষণ আচরণ সেটিংসের উপর নির্ভর করে এবং SH_WORD_SPLITবিকল্প দ্বারা প্রভাবিত হয় ।
উলিচ ড্যাঙ্গেল


3
একপাশে - সমস্ত ক্যাপগুলি ভেরিয়েবলের নামগুলি ভেরিয়েবল দ্বারা অপারেটিং সিস্টেম এবং শেলের সাথে অর্থ সহ ব্যবহার করা হয়; পসিক্স স্পেসিফিকেশন স্পষ্টভাবে অ্যাপ্লিকেশন সংজ্ঞায়িত ভেরিয়েবলের জন্য লোয়ার-কেস নাম ব্যবহার করার পরামর্শ দেয়। (উদ্ধৃত স্পেসিফিকেশনটি যখন বিশেষত পরিবেশের ভেরিয়েবলগুলিতে ফোকাস করছে, এনভায়রনমেন্ট ভেরিয়েবল এবং শেল ভেরিয়েবল একটি নেমস্পেস ভাগ করে: একটি এনভায়রনমেন্ট ভেরিয়েবলের দ্বারা ইতিমধ্যে ব্যবহৃত নামের সাথে একটি শেল ভেরিয়েবল তৈরি করার চেষ্টা পরবর্তীটির ওভাররাইট করে)। দেখুন pubs.opengroup.org/onlinepubs/009695399/basedefs/... , চতুর্থ অনুচ্ছেদ।
চার্লস ডাফি

উত্তর:


128

প্রথমে, zsh কে বাকী থেকে আলাদা করুন। এটি পুরানো বনাম আধুনিক শাঁসের বিষয় নয়: zsh আলাদা আচরণ করে। জেডএস ডিজাইনারগণ এটিকে traditionalতিহ্যবাহী শাঁসগুলির সাথে বেমানান করার সিদ্ধান্ত নিয়েছে (বোর্ন, কেএসএইচ, বাশ), তবে ব্যবহার সহজ।

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

সংক্ষেপে, যেখানে শব্দের তালিকা বা প্যাটার্ন আশা করা যায় সেখানে ডাবল উদ্ধৃতি আবশ্যক । এগুলি প্রাসঙ্গিক ক্ষেত্রে alচ্ছিক যেখানে পার্সার দ্বারা কাঁচা স্ট্রিং আশা করা যায়।

উদ্ধৃতি ছাড়া কি হয়

নোট করুন যে ডাবল উদ্ধৃতি ব্যতীত দুটি জিনিস ঘটে।

  1. প্রথমত, প্রসারণের ফলাফল (যেমন একটি প্যারামিটার বিকল্পের মতো পরিবর্তনশীলটির মান ${foo}, বা কমান্ড প্রতিস্থাপনের জন্য কমান্ডের আউটপুট $(foo)) যেখানে শব্দ থাকে সেখানে শব্দগুলিতে বিভক্ত হয়।
    আরও স্পষ্টভাবে, প্রসারণের ফলাফলটি প্রতিটি চরিত্রের মধ্যে বিভক্ত হয় যা IFSভেরিয়েবলের (বিভাজক চরিত্র) এর মান হিসাবে প্রদর্শিত হয় । বিভাজক অক্ষরের একটি ক্রম যদি সাদা স্থান (স্থান, ট্যাব বা নিউলাইন) ধারণ করে তবে শ্বেত স্থানটি একক অক্ষর হিসাবে গণনা করা হয়; নেতৃস্থানীয়, অনুসরণযোগ্য বা পুনরাবৃত্তি অ-শ্বেতস্পেস বিভাজনকারী খালি ক্ষেতগুলিতে নিয়ে যায়। উদাহরণস্বরূপ, সঙ্গে IFS=" :", :one::two : three: :four খালি ক্ষেত্র সামনে উৎপন্ন oneমধ্যে oneএবং twoমধ্যে, এবং (একটি একক একটি) threeএবং four
  2. বিভাজন থেকে প্রাপ্ত প্রতিটি ক্ষেত্রকে গ্লোব (একটি ওয়াইল্ডকার্ড প্যাটার্ন) হিসাবে ব্যাখ্যা করা হয় যদি এর মধ্যে একটি অক্ষর থাকে \[*?। যদি সেই প্যাটার্নটি এক বা একাধিক ফাইলের নামের সাথে মিলে যায় তবে প্যাটার্নটি ফাইলের নামের সাথে মিলে তালিকার দ্বারা প্রতিস্থাপন করা হবে।

একটি অব্যক্ত ভেরিয়েবল প্রসারিত কথাবার্তাটি $foo"স্প্লিট + গ্লোব অপারেটর" হিসাবে পরিচিত, এর বিপরীতে "$foo"যা ভেরিয়েবলের মান নেয় foo। কমান্ড প্রতিস্থাপনের ক্ষেত্রে একইটি ঘটে : "$(foo)"একটি কমান্ড প্রতিস্থাপন, একটি কমান্ড প্রতিস্থাপন, $(foo)যার পরে বিভাজন + গ্লোব হয়।

যেখানে আপনি ডাবল উদ্ধৃতি বাদ দিতে পারেন

বোর্ন-স্টাইলের শেলটিতে আমি ভাবতে পারি এমন সমস্ত ক্ষেত্রে এখানে আপনি ডাবল কোট ছাড়াই পরিবর্তনশীল বা কমান্ড প্রতিস্থাপন লিখতে পারেন, এবং মানটি আক্ষরিক অর্থে ব্যাখ্যা করা যায়।

  • একটি অ্যাসাইনমেন্টের ডানদিকে।

    var=$stuff
    a_single_star=*
    

    নোট করুন যে আপনার পরে ডাবল উদ্ধৃতি প্রয়োজন export, কারণ এটি একটি সাধারণ অন্তর্নির্মিত, কোনও কীওয়ার্ড নয়। এটি কেবলমাত্র কয়েকটি শেলের মধ্যে যেমন ড্যাশ, জেডএস (শি শিহরণে), যশ বা পশগুলিতে সত্য; bash এবং ksh উভয়ই exportবিশেষভাবে আচরণ করে।

    export VAR="$stuff"
  • এক caseবিবৃতিতে।

    case $var in 

    মনে রাখবেন যে কেস প্যাটার্নে আপনার ডাবল উদ্ধৃতি দরকার। শব্দ বিভাজন কেস প্যাটার্নে ঘটে না, তবে একটি উদ্ধৃত ভেরিয়েবলকে একটি প্যাটার্ন হিসাবে ব্যাখ্যা করা হয় যেখানে একটি উদ্ধৃত ভেরিয়েবলকে আক্ষরিক স্ট্রিং হিসাবে ব্যাখ্যা করা হয়।

    a_star='a*'
    case $var in
      "$a_star") echo "'$var' is the two characters a, *";;
       $a_star) echo "'$var' begins with a";;
    esac
    
  • ডাবল বন্ধনী মধ্যে। ডাবল বন্ধনী শেল বিশেষ সিনট্যাক্স হয়।

    [[ -e $filename ]]

    ডান দিকে: যে ছাড়া আপনি উদ্ধৃতি চিহ্ন যেখানে একটি প্যাটার্ন বা রেগুলার এক্সপ্রেশন বলে আশা করা হচ্ছে প্রয়োজন =বা ==বা !=বা =~

    a_star='a*'
    if [[ $var == "$a_star" ]]; then echo "'$var' is the two characters a, *"
    elif [[ $var == $a_star ]]; then echo "'$var' begins with a"
    fi
    

    আপনার একক বন্ধনী হিসাবে যথারীতি ডাবল উদ্ধৃতি প্রয়োজন [ … ]কারণ তারা সাধারণ শেল সিনট্যাক্স (এটি একটি আদেশ যা বলা হয় [)। দেখুন একক বা ডবল বন্ধনী

  • অ-ইন্টারেক্টিভ POSIX শেলগুলিতে পুনঃনির্দেশে (না bash, না ksh88)।

    echo "hello world" >$filename

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

  • গাণিতিক প্রকাশের ভিতরে। আসলে, একটি ভ্যারিয়েবলকে পাটিগণিতের এক্সপ্রেশন হিসাবে পার্স করার জন্য আপনাকে উদ্ধৃতিগুলি ছেড়ে দিতে হবে।

    expr=2*2
    echo "$(($expr))"
    

    তবে, পাটিগণিতের বিস্তারের চারপাশে আপনার উদ্ধৃতিগুলি দরকার কারণ এগুলি বেশিরভাগ শেলগুলিতে শব্দ বিভাজনের সাপেক্ষে যেমন পসিক্সের প্রয়োজন (!?)।

  • একটি সহযোগী অ্যারে সাবস্ক্রিপ্টে।

    typeset -A a
    i='foo bar*qux'
    a[foo\ bar\*qux]=hello
    echo "${a[$i]}"
    

একটি অব্যক্ত ভেরিয়েবল এবং কমান্ড প্রতিস্থাপন কিছু বিরল পরিস্থিতিতে কার্যকর হতে পারে:

  • যখন ভেরিয়েবল মান বা কমান্ড আউটপুট গ্লোব নিদর্শনগুলির একটি তালিকা নিয়ে গঠিত হয় এবং আপনি এই প্যাটার্নগুলি মিলে যাওয়া ফাইলগুলির তালিকায় প্রসারিত করতে চান।
  • আপনি যখন জানবেন যে মানটিতে কোনও ওয়াইল্ডকার্ডের অক্ষর নেই, এটি $IFSকোনও সংশোধন করা হয়নি এবং আপনি এটি সাদা বাক্সে পৃথক করতে চান split
  • যখন আপনি একটি নির্দিষ্ট চরিত্রের মধ্যে একটি মান বিভক্ত করতে চান: এর সাথে গ্লোব্বিং অক্ষম করুন set -f, IFSবিভাজক চরিত্রটি সেট করুন (বা একে একে হোয়াইটস্পেসে বিভক্ত করতে রেখে দিন), তারপরে প্রসারিত করুন।

Zsh

Zsh এ, আপনি কয়েকটি ব্যতিক্রম বাদ দিয়ে বেশিরভাগ সময় ডাবল উক্তি বাদ দিতে পারেন।

  • $varএকাধিক শব্দের ক্ষেত্রে কখনই প্রসারিত হয় না, তবে এটি খালি তালিকায় প্রসারিত হয় (একক, খালি শব্দযুক্ত তালিকার বিপরীতে) যদি মানটি varখালি স্ট্রিং হয়। কনট্রাস্ট:

    var=
    print -l $var foo        # prints just foo
    print -l "$var" foo      # prints an empty line, then foo
    

    একইভাবে, "${array[@]}"অ্যারের সমস্ত উপাদানগুলিতে প্রসারিত হয়, যখন $arrayকেবল খালি খালি উপাদানগুলিতে প্রসারিত হয়।

  • @পরামিতি সম্প্রসারণ পতাকা কখনও কখনও পুরো প্রতিকল্পন প্রায় ডবল কোট প্রয়োজন: "${(@)foo}"

  • কমান্ড প্রতিস্থাপনটি যদি অব্যক্ত থাকে তবে ক্ষেত্র বিভাজনের মধ্য দিয়ে যায়: echo $(echo 'a'; echo '*')প্রিন্ট a *(একক স্পেস সহ) যেখানে echo "$(echo 'a'; echo '*')"অপরিবর্তিত দুটি লাইনের স্ট্রিং প্রিন্ট করে। "$(somecommand)"একক কথায় কমান্ডের আউটপুট পেতে ব্যবহার করুন , চূড়ান্ত নিউলাইনগুলি। "${$(somecommand; echo _)%?}"চূড়ান্ত নিউলাইনগুলি সহ কমান্ডটির সঠিক আউটপুট পেতে ব্যবহার করুন । "${(@f)$(somecommand)}"কমান্ডের আউটপুট থেকে লাইনগুলির অ্যারে পেতে ব্যবহার করুন ।


আসলে, একটি ভ্যারিয়েবলকে পাটিগণিতের এক্সপ্রেশন হিসাবে পার্স করার জন্য আপনাকে উদ্ধৃতিগুলি ছেড়ে দিতে হবে। আমি কেন আপনার উদাহরণটি উদ্ধৃতি দিয়ে কাজ করতে সক্ষম:echo "$(("$expr"))"
সাইকেল

এটি যা man bashবলে: এক্সপ্রেশনটি এমনভাবে বিবেচনা করা হয় যেন এটি ডাবল কোটের মধ্যে থাকে তবে প্রথম বন্ধনের ভিতরে ডাবল উদ্ধৃতিটি বিশেষভাবে বিবেচনা করা হয় না।
সাইকেল

4
এছাড়াও, যে কেউ আগ্রহী তাদের পক্ষে স্প্লিট + গ্লোব এর আনুষ্ঠানিক নামগুলি শব্দ বিভাজন এবং পথের নাম প্রসারিত
সাইকেল

3
এফওয়াইআই - স্ট্যাকওভারফ্লোতে , আমার কাছে এই যুক্তিতে কোনও যুক্তি উদ্ধৃত না করার জন্য ডিফেন্ড করার জন্য কেউ " উত্তাল যখন একটি কাঁচা স্ট্রিং আশা করা হয়" টেনে নিয়েছিল echo। ভাষাটিকে আরও সুস্পষ্ট করার চেষ্টা করা উপযুক্ত হতে পারে ("যখন কোনও পার্সার দ্বারা কোনও কাঁচা স্ট্রিং আশা করা যায়", সম্ভবত?)
চার্লস ডাফি

2
@ চার্লস ডফি উঘ, আমি এই অপপ্রচারের কথা ভাবিনি। আপনার পরামর্শ অনুসারে আমি "যেখানে" "কখন" পরিবর্তিত হয়েছি এবং বাক্যটিকে শক্তিশালী করেছি।
গিলস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.