ব্যাশ / পসিক্স শেলের মধ্যে একটি ভেরিয়েবল উদ্ধৃত করতে ভুলে যাওয়ার সুরক্ষা সম্পর্কিত প্রভাব


206

আপনি যদি কিছুক্ষণ ধরে ইউনিক্স.স্ট্যাকেক্সেঞ্জোয়েন্ট ডটকমকে অনুসরণ করে চলেছেন তবে আপনার এখনই আশা করা উচিত যে echo $varবোর্নে / পসিক্স শেলের (যেমন হিসাবে ব্যতিক্রম) তালিকার প্রসঙ্গে (যেমনটি ব্যতীত zsh) একটি পরিবর্তনশীলকে ছেড়ে যাওয়াটির একটি বিশেষ অর্থ রয়েছে এবং আপনার খুব ভাল কারণ না থাকলে করা উচিত নয়।

এটি এখানে বেশ কয়েকটি প্রশ্নোত্তর দৈর্ঘ্যে আলোচনা করা হয়েছে (উদাহরণস্বরূপ: আমার শেল স্ক্রিপ্টটি সাদা স্থান বা অন্যান্য বিশেষ চরিত্রগুলিতে কেন চোকা দেয় ? , ডাবল-কোটেশন কখন প্রয়োজন ? , শেল ভেরিয়েবলের প্রসারণ এবং তার উপর গ্লোব এবং বিভক্তির প্রভাব , উদ্ধৃত) বনাম উদ্ধৃত স্ট্রিং প্রসার)

70০ এর দশকের শেষের দিকে বোর্ন শেলটি প্রথম প্রকাশের পর থেকে এটি ঘটেছে এবং কর্ন শেল ( ডেভিড কর্নের অন্যতম বৃহত্তম অনুশোচনা (প্রশ্ন #) )) দ্বারা পরিবর্তন করা হয়নি বা bashবেশিরভাগভাবে কর্ন শেলটি অনুলিপি করেছে এবং এটিই এটি কীভাবে পসিক্স / ইউনিক্স দ্বারা নির্দিষ্ট করা হয়েছে।

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

আমার অভিজ্ঞতায়, মূলত 3 ধরণের লোক রয়েছে যারা তাদের ভেরিয়েবলগুলি উদ্ধৃত করতে বাদ দেয়:

  • নতুনদের। এগুলি অবশ্যই স্বীকার করা যায় যে এটি একটি সম্পূর্ণ অনিরাপদ সিনট্যাক্স। এবং তাদের শিক্ষিত করার জন্য এই সাইটে আমাদের ভূমিকা।

  • ভুলে যাওয়া মানুষ

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

যদি আমরা এই ধরনের আচরণের সাথে সম্পর্কিত ঝুঁকিটি প্রকাশ করি তবে আমরা তাদের বোঝাতে পারি।

আপনি যদি নিজের ভেরিয়েবলগুলি উদ্ধৃত করতে ভুলে যান তবে এর চেয়ে খারাপটি কী হতে পারে। এটা সত্যিই হয় যে খারাপ?

আমরা এখানে কোন ধরণের দুর্বলতার কথা বলছি?

কোন প্রসঙ্গে এটি সমস্যা হতে পারে?


8
বাশপিত্সগুলি হ'ল এমন কিছু যা আপনার মনে হয়।
pawel7318

এই নিবন্ধটি থেকে ব্যাকলিংকটি আমি লিখেছিলাম , লেখার জন্য ধন্যবাদ
মীরাবিলোস

5
আমি একটি চতুর্থ গ্রুপ যুক্ত করার পরামর্শ দিতে চাই: যে লোকেরা অত্যধিক বার উদ্ধৃতি দেওয়ার জন্য মাথার উপরে আঘাত পেয়েছে তারা সম্ভবত তৃতীয় দলের সদস্যরা অন্যের প্রতি তাদের হতাশা প্রকাশ করে (শিকারটি বোকা হয়ে উঠছে)। অবশ্যই দুঃখজনক বিষয় হ'ল চতুর্থ গ্রুপের লোকেরা যখন বিষয়টি সবচেয়ে বেশি গুরুত্বপূর্ণ তখন বিষয়গুলি উদ্ধৃত করতে ব্যর্থ হতে পারে।
ack

উত্তর:


201

প্রস্তাবনা

প্রথমত, আমি বলব সমস্যাটি সমাধান করার সঠিক উপায় এটি নয়। এটি কিছুটা বলার মতো " আপনারা লোকদের খুন করবেন না কারণ অন্যথায় আপনি কারাগারে যাবেন "।

একইভাবে, আপনি আপনার পরিবর্তনশীলটি উদ্ধৃত করবেন না কারণ অন্যথায় আপনি সুরক্ষা দুর্বলতার পরিচয় দিচ্ছেন। আপনি আপনার ভেরিয়েবলগুলি উদ্ধৃত করেছেন কারণ এটি ভুল নয় (তবে জেলের ভয় যদি সহায়তা করতে পারে তবে কেন নয়)।

যারা কেবল ট্রেনে ঝাঁপিয়েছেন তাদের জন্য একটি সামান্য সংক্ষিপ্তসার।

সবচেয়ে শাঁস, একটি পরিবর্তনশীল সম্প্রসারণ unquoted (যদিও যে (এবং এই উত্তরটি বাকি) ও প্রতিকল্পন (কমান্ড প্রযোজ্য যাব `...`বা $(...)) এবং গাণিতিক সম্প্রসারণ ( $((...))বা $[...])) একটি খুব বিশেষ অর্থ আছে। এটা ব্যাখ্যা করার সবচেয়ে ভালো উপায় এটি অন্তর্নিহিত কিছু বাছাই invoking মত হল যে বিভক্ত + + উল্লিখিত glob operator¹।

cmd $var

অন্য ভাষায় কিছু লেখা হবে:

cmd(glob(split($var)))

$var$IFSবিশেষ প্যারামিটার ( বিভক্ত অংশ) জড়িত জটিল বিধি অনুসারে প্রথমে শব্দের তালিকায় বিভক্ত হয় এবং তারপরে বিভক্ত হওয়ার ফলে প্রতিটি শব্দকে একটি প্যাটার্ন হিসাবে বিবেচনা করা হয় যা এটির সাথে মেলে এমন ফাইলগুলির তালিকায় প্রসারিত হয় ( গ্লোব অংশ) ।

উদাহরণস্বরূপ, যদি $varথাকে *.txt,/var/*.xmlএবং $IFS রয়েছে ,, cmdআর্গুমেন্ট একটি সংখ্যা, প্রথম এক হচ্ছে সাথে কল করা হবে cmdএবং পরবর্তী বেশী হচ্ছে txt বর্তমান ডিরেক্টরির মধ্যে ফাইল এবং xmlফাইল /var

আপনি যদি cmdকেবল দুটি আক্ষরিক যুক্তি দিয়ে কল করতে চান cmd এবং *.txt,/var/*.xml, আপনি লিখতে চান:

cmd "$var"

যা আপনার অন্যান্য পরিচিত ভাষায় হবে:

cmd($var)

খোলসের দুর্বলতা বলতে আমরা কী বুঝি ?

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

ওয়েল, যদিও কেউ আপনাকে বলবে যে শেল স্ক্রিপ্টগুলি কখনই ওয়েব সিজিআই এর জন্য ব্যবহার করা উচিত নয়, বা ধন্যবাদ যে বেশিরভাগ সিস্টেমে সেটুড / সেটগিড শেল স্ক্রিপ্টগুলি আজকাল অনুমতি দেয় না, একটি জিনিস যা শেলশক (দূরবর্তীভাবে শোষণযোগ্য ব্যাশ বাগ যা তৈরি করেছে) 2014 সালের সেপ্টেম্বরের শিরোনামে) প্রকাশিত যে শেলগুলি এখনও ব্যাপকভাবে ব্যবহৃত হয় যেখানে তাদের সম্ভবত করা উচিত নয়: সিজিআইতে, ডিএইচসিপি ক্লায়েন্ট হুক স্ক্রিপ্টগুলিতে, সুডোর কমান্ডগুলিতে, (যদি না হয় ) সেতু কমান্ড দ্বারা আহবান করা হয় ...

মাঝে মাঝে অজান্তেই। উদাহরণস্বরূপ system('cmd $PATH_INFO') একটি php/ perl/ pythonসিজিআই স্ক্রিপ্টে সেই কমান্ড লাইনটি ব্যাখ্যা করার জন্য একটি শেলটি আহ্বান করা হয় না ( cmdনিজে নিজে শেল স্ক্রিপ্ট হতে পারে এবং এর লেখক কখনই এটি সিজিআই থেকে কল করার আশা করেনি)।

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

অবিচ্ছিন্নভাবে এর অর্থ হ'ল আক্রমণকারী ডেটা সরবরাহ করে, সেই ডেটাটি কোনও বিশেষাধিকারপ্রাপ্ত ব্যবহারকারী / প্রক্রিয়া দ্বারা প্রসেস করা হচ্ছে যা অজান্তেই কিছু করা উচিত নয় এমন কাজ করে, বেশিরভাগ ক্ষেত্রে বাগের কারণে of

মূলত, যখন আপনার বগি কোড আক্রমণকারীটির নিয়ন্ত্রণে ডেটা প্রক্রিয়া করে তখন আপনি একটি সমস্যা পেয়েছেন ।

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

ভেরিয়েবলের হিসাবে, কোনও সিজিআই স্ক্রিপ্টের ক্ষেত্রে এটি স্পষ্টতই স্পষ্টভাবে উপাত্ত হ'ল সিজিআই জিইটি / পোষ্ট প্যারামিটার এবং কুকিজ, পথ, হোস্ট ... প্যারামিটারের মতো জিনিস।

একটি সেটুইড স্ক্রিপ্টের জন্য (অন্যের দ্বারা আহ্বান করার সময় এক ব্যবহারকারী হিসাবে চলমান), এটি আর্গুমেন্ট বা পরিবেশের ভেরিয়েবল।

আরেকটি খুব সাধারণ ভেক্টর ফাইলের নাম। আপনি যদি কোনও ডিরেক্টরি থেকে একটি ফাইলের তালিকা পেয়ে থাকেন তবে আক্রমণকারী দ্বারা ফাইলগুলি সেখানে স্থাপন করা সম্ভব ।

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

তাও আবার একটা ~/.bashrcপ্রবন হতে পারে (উদাহরণস্বরূপ, bashযখন উপর প্রার্থনা তার ব্যাখ্যা হবে sshএকটি চালানোর জন্য ForcedCommand মত gitক্লায়েন্ট নিয়ন্ত্রণে কিছু ভেরিয়েবল দিয়ে সার্ভারে নিয়োজনগুলি)।

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

ব্যবসায় নিচে; এটা কতটুকু খারাপ?

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

প্রকৃতপক্ষে, শেল কোডে দুর্বলতার সন্ধান করার সময়, প্রথমে করণীয় হ'ল অব্যক্ত ভেরিয়েবলগুলি সন্ধান করা। এটি সহজেই স্পট করা যায়, প্রায়শই একজন ভাল প্রার্থী, সাধারণত আক্রমণকারী-নিয়ন্ত্রিত ডেটাতে ট্র্যাক করা সহজ।

অসমর্থিত পরিবর্তনশীলগুলি দুর্বলতায় রূপান্তরিত করতে পারে এমন অসংখ্য উপায় রয়েছে। আমি এখানে কয়েকটি সাধারণ ট্রেন্ড দেব।

তথ্য প্রকাশ

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

অবাঞ্ছিত বাহ্যিক ইনপুট নিয়ে গ্লোব্বিংয়ের অর্থ আক্রমণকারী আপনাকে যে কোনও ডিরেক্টরিতে লিখিত সামগ্রী পড়তে পারে।

ইন:

echo You entered: $unsanitised_external_input

যদি $unsanitised_external_inputএতে থাকে তবে এর /*অর্থ আক্রমণকারী এর সামগ্রী দেখতে পাবে /। কোন ব্যাপারই না. এটা যদিও আরো আকর্ষণীয় হয়ে সঙ্গে /home/*আপনি মেশিনে ব্যবহারকারী নামের একটি তালিকা দেয়, /tmp/*, /home/*/.forwardঅন্যান্য বিপজ্জনক চর্চা এ নির্দেশ, জন্য /etc/rc*/*সক্রিয় পরিষেবার জন্য ... কোন প্রয়োজন নেই পৃথকভাবে তাদের নাম। একটি মান /* /*/* /*/*/*...শুধুমাত্র পুরো ফাইল সিস্টেমের তালিকাবদ্ধ করবে।

পরিষেবা দুর্বলতা অস্বীকার।

পূর্ববর্তী কেসটি কিছুটা দূরে নিয়ে যাওয়া এবং আমরা একটি ডস পেয়েছি।

প্রকৃতপক্ষে, অচিরাচরিত ইনপুট সহ তালিকার প্রসঙ্গে যে কোনও উদ্বেগের পরিবর্তনশীল হ'ল কমপক্ষে একটি ডস দুর্বলতা।

এমনকি বিশেষজ্ঞ শেল স্ক্রিপ্টারগুলি সাধারণত এই জাতীয় জিনিস উদ্ধৃত করতে ভুলে যায়:

#! /bin/sh -
: ${QUERYSTRING=$1}

:কোন অপ-কমান্ড। সম্ভাব্য ভুল গুলো কী কী হতে পারতো?

যে দায়িত্ব অর্পণ করা বোঝানো হচ্ছে $1থেকে $QUERYSTRINGযদি $QUERYSTRING সেট না করা হয়। কমান্ড লাইন থেকে সিজিআই স্ক্রিপ্টকে কল করতে সক্ষম এটি একটি দ্রুত উপায়।

যে $QUERYSTRINGএখনো যদিও সম্প্রসারিত হয় এবং কারণ এটি উদ্ধৃত না, বিভক্ত + + উল্লিখিত glob অপারেটর প্রার্থনা করা হয়।

এখন, কিছু গ্লোব রয়েছে যেগুলি প্রসারিত করার জন্য বিশেষ ব্যয়বহুল। এর মধ্যে /*/*/*/*একটি যথেষ্ট খারাপ কারণ এর অর্থ ডিরেক্টরিগুলি 4 টি স্তর পর্যন্ত নীচে তালিকাবদ্ধ করা। ডিস্ক এবং সিপিইউ ক্রিয়াকলাপের পাশাপাশি, এর অর্থ হ'ল কয়েক হাজার ফাইল পাথ (40k এখানে একটি সর্বনিম্ন সার্ভার ভিএম-তে, যার মধ্যে 10k ডিরেক্টরি রয়েছে) সংরক্ষণ করা।

এখন /*/*/*/*/../../../../*/*/*/*40k x 10k এর অর্থ /*/*/*/*/../../../../*/*/*/*/../../../../*/*/*/*হ'ল এমনকি সবচেয়ে শক্তিশালী মেশিনটি তার হাঁটুতে আনতে যথেষ্ট।

এটি নিজের জন্য চেষ্টা করুন (যদিও আপনার মেশিনটি ক্র্যাশ বা ঝুলতে প্রস্তুত):

a='/*/*/*/*/../../../../*/*/*/*/../../../../*/*/*/*' sh -c ': ${a=foo}'

অবশ্যই, কোডটি যদি হয়:

echo $QUERYSTRING > /some/file

তারপরে আপনি ডিস্কটি পূরণ করতে পারেন।

শেল সিজি বা বাশ সিজি বা কেএস সিজি- তে কেবল একটি গুগল অনুসন্ধান করুন এবং আপনি কয়েকটি পৃষ্ঠা খুঁজে পাবেন যা শেলগুলিতে কীভাবে সিজিআই লিখতে হবে তা আপনাকে দেখায়। প্রক্রিয়া পরামিতিগুলির মধ্যে অর্ধেকটি কীভাবে দুর্বল are

এমনকি ডেভিড কর্নের নিজেরও দুর্বল (কুকি হ্যান্ডলিংয়ের দিকে দেখুন)।

যথেচ্ছ কোড কার্যকরকরণের দুর্বলতা পর্যন্ত

স্বেচ্ছাসেবীর কোড কার্যকর করা দুর্বলতার সবচেয়ে খারাপ ধরণের, যেহেতু আক্রমণকারী যদি কোনও কমান্ড চালাতে পারে, তবে সে কী করতে পারে তার কোনও সীমা নেই।

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

awk -v foo=$external_input '$2 == foo'

এখানে উদ্দেশ্যটি ছিল $external_inputশেল ভেরিয়েবলের সামগ্রীটি ভেরিয়েবলের কাছে বরাদ্দ করা foo awk

এখন:

$ external_input='x BEGIN{system("uname")}'
$ awk -v foo=$external_input '$2 == foo'
Linux

বিভাজনের ফলস্বরূপ দ্বিতীয় শব্দটি $external_input বরাদ্দ করা হয় না fooতবে awkকোড হিসাবে বিবেচনা করা হয় (এখানে এটি একটি স্বেচ্ছাসেবক আদেশ কার্যকর করে uname:)।

যে কমান্ড আছে যা অন্য কমান্ড নির্বাহ করতে পারেন জন্য বিশেষ একটা সমস্যা ( awk, env, sed(গনুহ এক), perl, find...) বিশেষত গনুহ রূপগুলো (যা আর্গুমেন্ট বিকল্প প্রয়োগ করা সম্ভব) সঙ্গে। কখনও কখনও, আপনি যেমন কমান্ডগুলি অন্যের মত কার্যকর করতে সক্ষম হবেন না ksh, bashবা zshএর [বা printf...

for file in *; do
  [ -f $file ] || continue
  something-that-would-be-dangerous-if-$file-were-a-directory
done

যদি আমরা ডাকা ডিরেক্টরি তৈরি করি x -o yes, তবে পরীক্ষাটি ইতিবাচক হয়, কারণ এটি একেবারে ভিন্ন শর্তাধীন অভিব্যক্তি যা আমরা মূল্যায়ন করছি।

সবচেয়ে খারাপ, যদি আমরা x -a a[0$(uname>&2)] -gt 1কমপক্ষে সমস্ত ksh বাস্তবায়ন (যার মধ্যে sh বেশিরভাগ বাণিজ্যিক ইউনিয়ন এবং কিছু BSD এর অন্তর্ভুক্ত) নামে একটি ফাইল তৈরি করা হয় , যা কার্যকর করে uname কারণ সেই শেলগুলি [কমান্ডের সংখ্যার তুলনা অপারেটরগুলিতে গাণিতিক মূল্যায়ন করে ।

$ touch x 'x -a a[0$(uname>&2)] -gt 1'
$ ksh -c 'for f in *; do [ -f $f ]; done'
Linux

bashযেমন একটি ফাইল নাম জন্য একই x -a -v a[0$(uname>&2)]

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

ফাইলের নাম দিয়ে সব ধরণের কাজ করা যায়।

$ touch -- '-R ..'
$ for file in *; do [ -f "$file" ] && chmod +w $file; done

এবং আপনি ..লেখার যোগ্য করে তোলেন (জিএনইউ দিয়ে পুনরাবৃত্তভাবে chmod)।

পাবলিক রাইটিংযোগ্য জায়গাগুলিতে ফাইলগুলির স্বয়ংক্রিয়ভাবে প্রসেসিং করা স্ক্রিপ্টগুলি /tmpখুব সাবধানতার সাথে লিখতে হবে।

কি সম্পর্কে [ $# -gt 1 ]

এটাই আমার ক্লান্তিকর মনে হচ্ছে। কিছু লোক এই ভেবে সমস্ত সমস্যায় নেমে পড়ে যে কোনও নির্দিষ্ট প্রসারণটি তারা উদ্ধৃতিগুলি বাদ দিতে পারে কিনা তা সিদ্ধান্ত নিতে সমস্যাযুক্ত কিনা।

এটা বলার মতো। আরে, এটা দেখে মনে হচ্ছে $#বিভক্ত + + উল্লিখিত glob অপারেটর সাপেক্ষে হতে পারে না, এর শেল বিভক্ত করতে + + এটা উল্লিখিত glob জিজ্ঞাসা করা যাক । বা আরে, আসুন ভুল কোডটি লিখি কারণ বাগটি আঘাত হানার সম্ভাবনা নেই

এখন এটি কতটা অসম্ভব? ঠিক আছে, $#(বা $!, $?বা কোনও গাণিতিক বিকল্প) কেবলমাত্র অঙ্কগুলি (বা কারও -জন্য) থাকতে পারে তাই গ্লোব অংশটি বাইরে। জন্য বিভক্ত অংশ যদিও কিছু করতে, সমস্ত আমরা প্রয়োজন হয় $IFSডিজিট (বা -)।

কিছু শাঁস দিয়ে, $IFSপরিবেশ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত হতে পারে, তবে পরিবেশটি নিরাপদ না থাকলে এটি যাইহোক খেলা।

এখন আপনি যদি একটি ফাংশন লিখেন:

my_function() {
  [ $# -eq 2 ] || return
  ...
}

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

# my_function
#   inputs:
#     $1: source directory
#     $2: destination directory
#   $IFS: used to split $#, expected not to contain digits...

এবং আপনার ক্রিয়াকলাপের কোডিংয়ের ক্ষেত্রে নিশ্চিত হওয়া $IFSদরকার যে অঙ্কগুলি নেই। সমস্ত কারণ আপনি এই 2 টি ডাবল-কোট অক্ষর টাইপ করা পছন্দ করেন নি।

এখন, এই [ $# -eq 2 ]বাগটি দুর্বলতা $IFSহওয়ার জন্য , আক্রমণকারীর নিয়ন্ত্রণে যাওয়ার জন্য আপনার কোনও প্রয়োজন । অনুমানযোগ্যভাবে, আক্রমণকারী যদি অন্য কোনও বাগটি প্রদর্শন না করে তবে সাধারণত এটি ঘটবে না ।

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

এই ক্ষেত্রে:

n=$(($1 + 1))
if [ $# -gt 2 ]; then
  echo >&2 "Too many arguments"
  exit 1
fi

এবং $1মান সহ একটি (IFS=-1234567890), পাটিগণিত মূল্যায়নের আইএফএসের সেটিংসের পার্শ্ব প্রতিক্রিয়া রয়েছে এবং পরবর্তী [ কমান্ড ব্যর্থ হয় যার অর্থ অনেকগুলি আর্গের জন্য চেককে বাইপাস করা হয়।

যখন স্প্লিট + গ্লোব অপারেটর চালু করা হবে না তখন কী হবে ?

ভেরিয়েবল এবং অন্যান্য বিস্তারের আশেপাশে কোটগুলির প্রয়োজন রয়েছে এমন আরও একটি মামলা রয়েছে: যখন এটি একটি নিদর্শন হিসাবে ব্যবহৃত হয়।

[[ $a = $b ]]   # a `ksh` construct also supported by `bash`
case $a in ($b) ...; esac

কিনা পরীক্ষা না $aএবং $b(সাধারণ আলোচনা ছাড়া একই zsh) কিন্তু যদি $aএ ধরণের সাথে মেলা $b। আর তুমি উদ্ধৃত করা প্রয়োজন $bযদি আপনি স্ট্রিং হিসাবে তুলনা করতে চান (একই জিনিস মধ্যে "${a#$b}"বা "${a%$b}"বা "${a##*$b*}"যেখানে $bউদ্ধৃত করা উচিত তাই না একটি প্যাটার্ন হিসাবে গ্রহণ করা)।

এর অর্থ হ'ল এটি সেই [[ $a = $b ]]ক্ষেত্রে সত্য হতে পারে যেখানে উদাহরণস্বরূপ (যখন হয় এবং যখন থাকে ) $aথেকে আলাদা হয় বা মিথ্যা ফিরে আসতে পারে যখন তারা অভিন্ন হয় (উদাহরণস্বরূপ যখন উভয় এবং হয় )।$b$aanything$b*$a$b[a]

এটি কি সুরক্ষা দুর্বলতার জন্য তৈরি করতে পারে? হ্যাঁ, যে কোনও বাগের মতো। এখানে, আক্রমণকারী আপনার স্ক্রিপ্টের লজিকাল কোড প্রবাহকে পরিবর্তন করতে পারে এবং / অথবা আপনার স্ক্রিপ্টটি করছে এমন অনুমানগুলি ভেঙে দিতে পারে। উদাহরণস্বরূপ, একটি কোড সহ:

if [[ $1 = $2 ]]; then
   echo >&2 '$1 and $2 cannot be the same or damage will incur'
   exit 1
fi

আক্রমণকারী পাসের মাধ্যমে চেকটি বাইপাস করতে পারে '[a]' '[a]'

এখন, যদি সেই প্যাটার্নটি মিলে না যায় বা বিভক্ত + গ্লোব অপারেটর প্রয়োগ না হয় তবে একটি পরিবর্তনশীল অকেজো রেখে যাওয়ার বিপদ কী?

আমি স্বীকার করতে হবে যে আমি লিখি:

a=$b
case $a in...

সেখানে, উদ্ধৃতি ক্ষতি করে না তবে কঠোরভাবে প্রয়োজনীয় নয়।

যাইহোক, এই ক্ষেত্রে (উদাহরণস্বরূপ প্রশ্নোত্তর উত্তরগুলিতে) উদ্ধৃতিগুলি বাদ দেওয়ার একটি পার্শ্ব প্রতিক্রিয়া হ'ল এটি প্রাথমিকভাবে একটি ভুল বার্তা পাঠাতে পারে : যাতে ভেরিয়েবলগুলি উদ্ধৃত না করা সব ঠিক

উদাহরণস্বরূপ, তারা ভাবতে শুরু করতে পারে যে যদি a=$bঠিক থাকে তবে তাওexport a=$b হয়ে যাবে (যা এটি অনেকগুলি শেলের মধ্যে নেই যেমন exportকমান্ডের পক্ষে যুক্তি হিসাবে তাই তালিকা প্রসঙ্গে) বা env a=$b

কি হবে zsh?

zshএই নকশা বিশিষ্টতা বেশিরভাগ স্থির করে। ইন zsh(অন্তত যখন SH / ksh এমুলেশন মোড নেই), যদি আপনি চান বিভাজন , বা globbing , অথবা প্যাটার্ন ম্যাচিং , আপনি এটি স্পষ্টভাবে অনুরোধ করতে আছে: $=varবিভক্ত করতে, এবং $~varউল্লিখিত glob অথবা পরিবর্তনশীল বিষয়বস্তুর জন্য যেমন চিকিত্সা করা একটি প্যাটার্ন.

যাইহোক, বিভাজন (তবে গ্লোব্বিং নয়) অব্যক্ত কমান্ড প্রতিস্থাপন (যেমন হিসাবে echo $(cmd)) উপর স্পষ্টভাবে সম্পন্ন হয় ।

এছাড়াও, পরিবর্তনশীলকে উদ্ধৃত না করার একটি কখনও কখনও অযাচিত পার্শ্ব প্রতিক্রিয়া হ'ল খালি অপসারণzshআচরণ কি আপনি অন্য শেল মধ্যে (সঙ্গে পুরাপুরি globbing অক্ষম করার মাধ্যমে অর্জন করতে পারেন অনুরূপ set -f) এবং বিভাজন (সঙ্গে IFS='')। এখনও:

cmd $var

কোনও বিভাজন + গ্লোব থাকবে না , তবে যদি $varখালি থাকে তবে একটি খালি যুক্তি পাওয়ার পরিবর্তে cmdকোনও যুক্তিই পাবেন না।

এটি ত্রুটিগুলি সৃষ্টি করতে পারে (স্পষ্টর মতো [ -n $var ])। এটি সম্ভবত কোনও স্ক্রিপ্টের প্রত্যাশা এবং অনুমানগুলি ভঙ্গ করতে পারে এবং দুর্বলতার কারণ হতে পারে, তবে আমি এখনই খুব বেশি-দূরবর্তী উদাহরণ নিয়ে আসতে পারি না)।

কি যখন আপনি কি করতে প্রয়োজন বিভক্ত + + উল্লিখিত glob অপারেটর?

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

উপসংহার

সংক্ষেপে, শেলগুলিতে নিরবচ্ছিন্ন একটি পরিবর্তনশীল (বা কমান্ড প্রতিস্থাপন বা গাণিতিক সম্প্রসারণ) রেখে যাওয়া খুব বিপজ্জনক হতে পারে বিশেষত যখন ভুল প্রসঙ্গে প্রাসঙ্গিক কাজগুলি করা হয়, এবং এটি ভুল বিষয়গুলি কী তা জানা খুব শক্ত।

এটি খারাপ অভ্যাস হিসাবে বিবেচিত হওয়ার অন্যতম কারণ ।

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

(এবং এটি এখনও সুস্পষ্ট না হলে, শেলগুলিতে সুরক্ষা সংবেদনশীল কোডটি এড়াতে দয়া করে)।

এবং দয়া করে এই সাইটে আপনার উত্তরগুলিতে আপনার পরিবর্তনগুলি উদ্ধৃত করুন!


And ksh93এবং pdkshএবং ডেরিভেটিভগুলিতে, গ্লোববিং অক্ষম না করা ছাড়াও ব্রেস সম্প্রসারণ করা হয় ( বিকল্প অক্ষম ksh93থাকা সত্ত্বেও, ksh93u + পর্যন্ত সংস্করণগুলির ক্ষেত্রে braceexpand)।


উল্লেখ্য, এর সাথে [[কেবল তুলনামূলক আরএইচএসের উদ্ধৃতি দেওয়া দরকার:if [[ $1 = "$2" ]]; then
মীরাবিলোস

2
হ্যাঁ, @mirabilos কিন্তু LHS প্রয়োজন না না উদ্ধৃত করা, তাই কোন বাধ্যকারী কারণ সেখানে এটি উদ্ধৃত করা না (যদি আমরা সচেতন সিদ্ধান্ত নেওয়া করতে চলেছেন ডিফল্টরূপে উদ্ধৃত হিসাবে এটা করতে সবচেয়ে ইন্দ্রিয়গ্রাহ্য জিনিস মনে করা হয় )। এছাড়াও মনে রাখবেন যে এর প্রথম চরিত্রটি স্থানের সাথে [[ $* = "$var" ]]একই নয় (এবং এছাড়াও যদি খালি হয় তবে আমি ঠিক কি তার সমান কিনা তা নিশ্চিত নই, আমি কি কোনও বাগ উত্থাপন করব?))। [[ "$*" = "$var" ]]$IFSbashmksh$IFS$*
স্টাফেন চেজেলাস

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

2
@ বারমার, ধরে নিচ্ছেন আপনি বোঝাতে চেয়েছেন foo='bar; rm *', এটি হবে না, তবে এটি বর্তমান ডিরেক্টরিটির বিষয়বস্তু তালিকাভুক্ত করবে যা তথ্য প্রকাশ হিসাবে গণ্য হতে পারে। print $fooমধ্যে ksh93(যেখানে printজন্য প্রতিস্থাপন করা হয় echoযে তার ভুলত্রুটি কিছু ঠিকানাগুলি) (সঙ্গে উদাহরণস্বরূপ যদিও একটি কোড ইনজেকশন দুর্বলতার আছে foo='-f%.0d z[0$(uname>&2)]') (আপনি আসলে প্রয়োজন print -r -- "$foo"echo "$foo"এখনো ভুল ও নির্ধার্য নয় (যদিও সাধারণত কম ক্ষতিকর))।
স্টাফেন চেজেলাস

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

34

[দ্বারা অনুপ্রাণিত এই উত্তরটি দ্বারা CA গুলির ।]

তবে কি হবে…?

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

এবং যদি সম্ভাব্য মানগুলির মধ্যে একটি হ'ল খালি স্ট্রিং, এবং আমি "খালি অপসারণ" এর উপর নির্ভরশীল? উদাহরণস্বরূপ, যদি ভেরিয়েবলে খালি স্ট্রিং থাকে তবে আমি আমার কমান্ডে খালি স্ট্রিং পেতে চাই না; আমি কিছুই পেতে চাই। উদাহরণ স্বরূপ,

যদি কিছু_ শর্ত
তারপর
    ignorecase = "- আমি"
আর
    ignorecase = ""
ফাই
                                        # মনে রাখবেন যে, উপরে আদেশগুলিতে উদ্ধৃতি চিহ্ন আছে না কঠোরভাবে প্রয়োজন ছিল। 
, grep $ ignorecase   other_ , grep _args

আমি বলতে পারি না ; খালি স্ট্রিং হলে এটি ব্যর্থ হবে ।grep "$ignorecase" other_grep_args$ignorecase

প্রতিক্রিয়া:

অন্য উত্তরে যেমন আলোচনা করা হয়েছে, IFSএতে একটি -বা একটি রয়েছে তবে এটি এখনও ব্যর্থ হবে i। যদি আপনি নিশ্চিত হয়ে থাকেন যে IFSআপনার ভেরিয়েবলের কোনও অক্ষর নেই (এবং আপনি নিশ্চিত যে আপনার ভেরিয়েবলটিতে কোনও গ্লোব অক্ষর নেই) তবে এটি সম্ভবত নিরাপদ।

তবে এমন একটি উপায় রয়েছে যা নিরাপদ (যদিও এটি কিছুটা কুৎসিত এবং বেশ স্বতঃস্ফূর্ত): ব্যবহার ${ignorecase:+"$ignorecase"}। থেকে POSIX শেল কমান্ড ভাষা স্পেসিফিকেশন অধীন  2.6.2 প্যারামিটার সম্প্রসারণ ,

${parameter:+[word]}

    বিকল্প মান ব্যবহার করুন।   যদি parameterসেট না করা বা শূন্য হয়, নাল প্রতিস্থাপন করা হবে; অন্যথায়, word (বা wordবাদ দেওয়া যদি খালি স্ট্রিং ) এর বিস্তৃতি প্রতিস্থাপন করা হবে।

এখানে কৌশল যেমন এটি হ'ল আমরা এটি ignorecaseহিসাবে parameter এবং "$ignorecase"হিসাবে ব্যবহার করছি word। সুতরাং ${ignorecase:+"$ignorecase"}মাধ্যম

যদি $ignorecaseআনসেট বা শূন্য হয় (অর্থাত, খালি), নাল (অর্থাত, অব্যক্ত কিছুই নয় ) প্রতিস্থাপন করা হবে; অন্যথায়, এর সম্প্রসারণ "$ignorecase"বিকল্প হবে।

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


তবে কি হবে…?

তবে আমার যদি এমন একটি পরিবর্তনশীল থাকে যা আমি চাই / শব্দের মধ্যে বিভক্ত করা প্রয়োজন? (এটি অন্যথায় প্রথম কেসের মতো; আমার স্ক্রিপ্টটি ভেরিয়েবল সেট করেছে এবং আমি নিশ্চিত যে এটিতে কোনও গ্লোব অক্ষর নেই But তবে এতে স্থান (গুলি) থাকতে পারে এবং আমি চাই যে এটি স্পেসে পৃথক যুক্তিগুলিতে বিভক্ত হবে) সীমানা।
পিএস আমি এখনও খালি অপসারণ চাই want)

উদাহরণ স্বরূপ,

যদি কিছু_ শর্ত
তারপর
    মানদণ্ড = "- টাইপ চ"
আর
    মানদণ্ড = ""
ফাই
যদি কিছু_আর_শক্তি
তারপর
    মানদণ্ড = "$ মানদণ্ড -সময়ের +42"
ফাই
"$ start_directory" $ মানদণ্ড খুঁজে   other_ এটি _args

প্রতিক্রিয়া:

আপনি ভাবতে পারেন এটি ব্যবহারের ক্ষেত্রে এটি eval  না!   এমনকি evalএখানে ব্যবহার সম্পর্কে চিন্তাভাবনা করার লোভকে প্রতিহত করুন।

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

তবে, আপনি যদি ব্যাশ ব্যবহার করছেন (বা ksh, zsh বা yash), তবে একটি উপায় নিরাপদ: একটি অ্যারে ব্যবহার করুন:

যদি কিছু_ শর্ত
তারপর
    মানদণ্ড = (- টাইপ চ) # আপনি বলতে পারেন `মানদণ্ড = (" - টাইপ "" চ ")`, তবে এটি সত্যই অপ্রয়োজনীয়।
আর
    মানদণ্ড = () # এই আদেশে কোনও উদ্ধৃতি ব্যবহার করবেন না !
ফাই
যদি কিছু_আর_শক্তি
তারপর
    মানদণ্ড + = (- এমটাইম +৪২) # দ্রষ্টব্য: অ্যারেতে যোগ (সংযোজন) করতে `=` নয়, তবে ` + =`।
ফাই
এটি "$ start_directory" "$ {মানদণ্ড [@]}"   other_ এটি _args

বাশ থেকে (1) ,

অ্যারের কোনও উপাদান ব্যবহার করে রেফারেন্স করা যেতে পারে । … যদি হয় বা হয়  তবে শব্দটি সমস্ত সদস্যের কাছে প্রসারিত হয় । এই সাবস্ক্রিপ্টগুলি কেবল তখনই পৃথক হয় যখন শব্দটি ডাবল কোটের মধ্যে উপস্থিত হয়। যদি শব্দটি ডাবল-কোটেড হয় ... ... প্রতিটি উপাদানকে পৃথক শব্দের দিকে প্রসারিত করে ।${name[subscript]}subscript@*name${name[@]}name

সুতরাং "${criteria[@]}"প্রসারিত (উপরের উদাহরণে) শূন্য, দুই বা চারটি উপাদান criteria, প্রতিটি উদ্ধৃত হয়েছে। বিশেষত, যদি কন্ডিশনের  দুটিই সত্য না হয় তবে criteriaঅ্যারেতে কোনও বিষয়বস্তু থাকে না ( criteria=()বিবৃতি অনুসারে সেট করা থাকে ) এবং কিছুই"${criteria[@]}" মূল্যায়ন করে না (এমনকি কোনও অসুবিধাগুলি খালি স্ট্রিংও নয়)।


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

printf "সন্ধানের জন্য ফাইলের নাম লিখুন:"
নাম পড়ুন
যদি ["$ fname"! = ""]
তারপর
    মানদণ্ড + = (- নাম "name fname")
ফাই

নোট করুন যে প্রতিটি সময় এটি ব্যবহার করা $fnameহয় উদ্ধৃত করা হয়। এমনকি ব্যবহারকারী যদি এর মতো কিছু প্রবেশ করে বা এটি কাজ করে ;  বা মূল্যায়ন । (মনে রাখবেন অ্যারের প্রতিটি উপাদান উদ্ধৃত হয়েছে))foo barfoo*"${criteria[@]}"-name "foo bar"-name "foo*"

অ্যারেগুলি সমস্ত পসিক্স শেলগুলিতে কাজ করে না; অ্যারেগুলি হ'ল কেএসএস / বাশ / জেডএস / যশ-ইসএম। ব্যতীত ... সমস্ত শেল সমর্থন করে এমন একটি অ্যারে রয়েছে: আর্গুমেন্ট তালিকা, ওরফে "$@"। আপনি যদি যুক্তি তালিকার সাথে সম্পন্ন হয়ে থাকেন তবে আপনাকে (যেমন, আপনি সমস্ত "অবস্থানীয় পরামিতি" (আর্গুমেন্টগুলি ভেরিয়েবলগুলিতে অনুলিপি করেছেন, বা অন্যথায় সেগুলি প্রক্রিয়া করেছেন), আপনি আরগ তালিকাটি অ্যারে হিসাবে ব্যবহার করতে পারেন:

যদি কিছু_ শর্ত
তারপর
    সেট - -প্রকার চ # আপনি বলতে পারেন `সেট -" -প্রকার "" চ "`, তবে এটি সত্যই অপ্রয়োজনীয়।
আর
    সেট -
ফাই
যদি কিছু_আর_শক্তি
তারপর
    সেট - "$ @" -মটাইম +42
ফাই
# একইভাবে: সেট - "$ @" -নাম "$ নাম"
এটি "$ start_directory" "$ @"   other_ এটি _args

"$@"কনস্ট্রাক্ট (যা ঐতিহাসিকভাবে, প্রথম এসেছিলেন) হিসাবে একই শব্দার্থবিদ্যা হয়েছে - এটা প্রতিটি যুক্তি বিস্তৃতি (অর্থাত, যুক্তি তালিকাটির প্রতিটি উপাদান) একটি পৃথক শব্দ হিসাবে যদি আপনার দ্বারা টাইপ করা ছিল ।"${name[@]}""$1" "$2" "$3" …

২.৪.২ বিশেষ প্যারামিটারের অধীনে, পসিক্স শেল কমান্ড ভাষার স্পেসিফিকেশন থেকে অংশ নেওয়া ,

@

    এক থেকে শুরু করে, প্রতিটি পজিশনাল প্যারামিটারের জন্য প্রথমে একটি ক্ষেত্র প্রস্তুত করে যা স্থিতিগত পরামিতিগুলিতে প্রসারিত হয়। …, প্রাথমিক ক্ষেত্রগুলি পৃথক ক্ষেত্র হিসাবে ধরে রাখা হবে,…। যদি কোনও অবস্থানগত পরামিতি না থাকে তবে ডাবল-কোটের মধ্যে থাকা @সত্ত্বেও এর সম্প্রসারণ শূন্য ক্ষেত্র উত্পন্ন করবে @; ...

পুরো পাঠ্যটি কিছুটা রহস্যজনক; মূল বিষয়টি হ'ল এটি নির্দিষ্ট করে যে "$@"শূন্য ক্ষেত্র উত্পন্ন করবে যখন কোনও অবস্থানিক পরামিতি নেই। Noteতিহাসিক দ্রষ্টব্য: ১৯ 1979৯ "$@"সালে যখন প্রথম বোর্ন শেল (বাশের পূর্বসূরী) এ প্রথম পরিচয় হয়েছিল, তখন কোনও বাগ "$@"অবস্থান ছিল যখন কোনও অবস্থানগত পরামিতি না থাকায় একক খালি স্ট্রিং দ্বারা প্রতিস্থাপন করা হয়েছিল; দেখতে কি নেই ${1+"$@"}একটি শেল স্ক্রিপ্ট-এ বলতে চাচ্ছি, এবং কিভাবে এটা থেকে পৃথক "$@"? প্রথাগত বোর্ন শেল পরিবারকি করে ${1+"$@"}অর্থ ... এবং যেখানে এটি প্রয়োজন? , এবং "$@"বনাম${1+"$@"}


অ্যারে প্রথম অবস্থাতেও সহায়তা করে:

যদি কিছু_ শর্ত
তারপর
    অবহেলা = (- আমি) # আপনি বলতে পারেন `উপেক্ষা = (" - আমি ")`, তবে এটি সত্যিই অপ্রয়োজনীয়।
আর
    উপেক্ষা = () # এই আদেশে কোনও উদ্ধৃতি ব্যবহার করবেন না !
ফাই
, grep "$ {ignorecase [@]}"   other_ , grep _args

____________________

পিএস (সিএসএস)

এটি বলার অপেক্ষা রাখে না, তবে লোকেদের পক্ষে যারা এখানে নতুন রয়েছেন: সিএসএস, টিসিএইচ, ইত্যাদি বোর্ন / পসিক্স শেল নয়। তারা সম্পূর্ণ ভিন্ন পরিবার। অন্য রঙের একটি ঘোড়া। একটি সম্পূর্ণ অন্যান্য বল খেলা। বিড়ালের বিভিন্ন জাত। অন্য পালকের পাখি। এবং, বিশেষত, কৃমি একটি পৃথক ক্যান।

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


1
মনে রাখবেন যে, মধ্যে csh, আপনি বরং ব্যবহার করতে চাই $var:qচেয়ে "$var"যেমন আধুনিক ভেরিয়েবল যে সম্পর্কে newline অক্ষর জন্য কাজ করে না (অথবা আপনি স্বতন্ত্রভাবে অ্যারের উপাদান উদ্ধৃত করা বদলে একটি একক যুক্তি মধ্যে ব্যবধান সহ তাদের যোগদান করতে চান তাহলে)।
স্টাফেন চেজেলাস

ব্যাশে, সাথে bitrate="--bitrate 320"কাজ করে ${bitrate:+$bitrate}এবং bitrate=--bitrate 128কাজ করবে না ${bitrate:+"$bitrate"}কারণ এটি আদেশটি ভঙ্গ করে। ব্যবহার করা নিরাপদ ${variable:+$variable}সঙ্গে "?
ফ্রিডো

@ ফ্রেডো: আমি আপনার মন্তব্যটি অস্পষ্ট বলে মনে করি। আমি বিশেষত অস্পষ্ট যে আপনি কী জানতে চান যা আমি ইতিমধ্যে বলিনি। দ্বিতীয়টি "তবে কী হবে" শিরোনামটি দেখুন - "তবে আমার যদি এমন একটি পরিবর্তনশীল থাকে যা আমি চাই / শব্দের মধ্যে বিভক্ত করা প্রয়োজন?" এটি আপনার পরিস্থিতি, এবং আপনার সেখানে পরামর্শ অনুসরণ করা উচিত। তবে আপনি যদি না করতে পারেন (উদাঃ, কারণ আপনি বাশ, ksh, zsh বা যশ ছাড়া অন্য কোনও শেল ব্যবহার করছেন এবং আপনি $@অন্য কোনও কিছুর জন্য ব্যবহার করছেন  ), বা অন্য কারণে আপনি কেবল অ্যারে ব্যবহার করতে অস্বীকার করছেন, আমি উল্লেখ করি আপনাকে "অন্যান্য উত্তরে যেমন আলোচনা করা হয়েছে"। … (চালিয়ে যাওয়া)
জি ম্যান

(Cont'd) ... আপনার প্রস্তাবনা (ব্যবহার ${variable:+$variable}সঙ্গে ") ব্যর্থ যদি IFS রয়েছে করবে  -,  0, 2, 3, a, b, e, i, rবা  t
জি ম্যান

ঠিক আছে আমার ভেরিয়েবলের a, e, b, i 2 এবং 3 টি অক্ষর রয়েছে এবং এখনও এটি ভাল কাজ করে${bitrate:+$bitrate}
ফ্রিডো

11

আমি স্টাফেনের জবাব সম্পর্কে সন্দেহবাদী ছিলাম, তবে এটি আপত্তিজনকভাবে সম্ভব $#:

$ set `seq 101`

$ IFS=0

$ echo $#
1 1

বা $ ?:

$ IFS=0

$ awk 'BEGIN {exit 101}'

$ echo $?
1 1

এগুলি নিখুঁত উদাহরণ, তবে সম্ভাবনা রয়েছে।

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