বাশে ওয়াইল্ডকার্ড / নক্ষত্রের চরিত্রটি কীভাবে আমি পালাব?


136

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

me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR

এবং \পালানোর চরিত্রটি ব্যবহার করে :

me$ FOO="BAR \* BAR"
me$ echo $FOO
BAR \* BAR

আমি অবশ্যই বোকামি কিছু করছি।

আমি কীভাবে আউটপুট পাব BAR * BAR?

উত্তর:


139

সেটিং করার সময় উদ্ধৃতি দেওয়া $FOOযথেষ্ট নয়। আপনার পরিবর্তনশীল রেফারেন্সটিও উদ্ধৃত করতে হবে:

me$ FOO="BAR * BAR"
me$ echo "$FOO"
BAR * BAR

8
এটি রহস্যজনক, কেন এটি? কি হচ্ছে?
তোফুটিম

কারণ ভেরিয়েবলগুলি প্রসারিত হয়
ড্যানিয়েল

103

সংক্ষিপ্ত উত্তর

অন্যরা যেমন বলেছে - অদ্ভুত আচরণ রোধ করতে আপনার সর্বদা চলকগুলি উদ্ধৃত করা উচিত। সুতরাং শুধু প্রতিধ্বনি instead foo এর পরিবর্তে প্রতিধ্বনি "। Foo" ব্যবহার করুন ।

দীর্ঘ উত্তর

আমি মনে করি যে এই উদাহরণটি আরও ব্যাখ্যা দেয় কারণ এটির চেহারার চেয়ে বেশি দেখা যাচ্ছে more

আমি দেখতে পাচ্ছি কোথায় আপনার বিভ্রান্তি আসে কারণ আপনি নিজের প্রথম উদাহরণটি চালানোর পরে আপনি সম্ভবত নিজেকে ভেবেছিলেন যে শেলটি অবশ্যই করছে:

  1. প্যারামিটার সম্প্রসারণ
  2. ফাইলের নাম সম্প্রসারণ

সুতরাং আপনার প্রথম উদাহরণ থেকে:

me$ FOO="BAR * BAR"
me$ echo $FOO

প্যারামিটার সম্প্রসারণের পরে সমান:

me$ echo BAR * BAR

এবং ফাইলের নাম সম্প্রসারণ সমান:

me$ echo BAR file1 file2 file3 file4 BAR

এবং আপনি যদি কেবল echo BAR * BARকমান্ড লাইনে টাইপ করেন তবে দেখতে পাবেন যে সেগুলি সমান।

সুতরাং আপনি সম্ভবত নিজেকে ভেবেছিলেন "আমি যদি * এড়িয়ে চলি তবে আমি ফাইলের নামটি বাড়াতে পারি"

সুতরাং আপনার দ্বিতীয় উদাহরণ থেকে:

me$ FOO="BAR \* BAR"
me$ echo $FOO

প্যারামিটার সম্প্রসারণের পরে সমতুল্য হওয়া উচিত:

me$ echo BAR \* BAR

এবং ফাইলের নাম সম্প্রসারণের সমতুল্য হওয়া উচিত:

me$ echo BAR \* BAR

এবং যদি আপনি কমান্ড লাইনে সরাসরি "প্রতিধ্বনি বার * * বার" টাইপ করার চেষ্টা করেন তবে এটি অবশ্যই "বার * বার" মুদ্রণ করবে কারণ ফাইলের নাম প্রসারিত হওয়ার ফলে বাধা দেওয়া হয়েছিল।

তাহলে $ foo ব্যবহার করা কেন কাজ করে না?

এটি ঘটে কারণ সেখানে তৃতীয় সম্প্রসারণ ঘটে যা উদ্ধৃতি অপসারণ। বাশ ম্যানুয়াল থেকে উদ্ধৃতিটি হ'ল:

পূর্ববর্তী প্রসারণের পরে, 'of', '' ', এবং' "'অক্ষরের সমস্ত অনুচ্চারিত ঘটনাগুলি উপরের বিস্তারের কোনওটি থেকে সরানো হয়নি।

সুতরাং যা ঘটে যখন আপনি কমান্ড লাইনে সরাসরি কমান্ডটি টাইপ করেন, পালানোর চরিত্রটি কোনও পূর্ববর্তী প্রসারণের ফলাফল নয় তাই BASH এটি প্রতিধ্বনি কমান্ডে প্রেরণের আগে এটি সরিয়ে দেয়, তবে দ্বিতীয় উদাহরণে "" * "ছিল পূর্ববর্তী প্যারামিটার বিস্তারের ফলাফল, সুতরাং এটি সরানো হয়নি। ফলস্বরূপ, প্রতিধ্বনি "\ *" পান এবং এটি এটি প্রিন্ট করে।

প্রথম উদাহরণের মধ্যে পার্থক্যটি লক্ষ্য করুন - "*" এমন অক্ষরগুলির অন্তর্ভুক্ত নয় যা উদ্ধৃতি অপসারণ দ্বারা সরানো হবে।

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

বেস বিস্তারের সম্পূর্ণ ব্যাখ্যার জন্য, দেখুন:

http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions


1
দুর্দান্ত উত্তর! এখন আমি মনে হয় না যে আমি এমন বোবা প্রশ্ন জিজ্ঞাসা করেছি। :-)
andyuk

1
বিশেষ চরিত্রগুলি এড়াতে কিছু ইউটিলিটি আছে?
জিগার জোশী

"আপনার সবসময় অদ্ভুত আচরণ রোধ করতে ভেরিয়েবলগুলি উদ্ধৃত করা উচিত" - আপনি যখন এগুলি স্ট্রিং হিসাবে ব্যবহার করতে চান
অ্যাঞ্জেলো


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

54

আমি এই পুরানো থ্রেডে কিছুটা যুক্ত করব।

সাধারণত আপনি ব্যবহার করবেন

$ echo "$FOO"

তবে এই সিনট্যাক্স নিয়েও আমার সমস্যা হয়েছিল। নিম্নলিখিত স্ক্রিপ্ট বিবেচনা করুন।

#!/bin/bash
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"

*চাহিদা ধারণকৃত পাস করা curl, কিন্তু একই সমস্যা দেখা দেয় হবে। উপরের উদাহরণটি কাজ করবে না (এটি বর্তমান ডিরেক্টরিতে ফাইলের নামগুলিতে প্রসারিত হবে) এবং তাও করবে না \*। আপনি উদ্ধৃতিও দিতে পারেন না $curl_optsকারণ এটিতে একটি একক (অবৈধ) বিকল্প হিসাবে স্বীকৃত হবে curl

curl: option -s --noproxy * -O: is unknown
curl: try 'curl --help' or 'curl --manual' for more information

অতএব আমি বিশ্বব্যাপী প্যাটার্নে প্রয়োগ করা হয় বা বিল্ট-ইন পতাকা ব্যবহার করে পুরোপুরিভাবে ফাইলের নাম রোধ করতে bashভেরিয়েবলের ব্যবহারের পরামর্শ দেব ।$GLOBIGNOREset -f

#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"  ## no filename expansion

আপনার মূল উদাহরণ প্রয়োগ করা:

me$ FOO="BAR * BAR"

me$ echo $FOO
BAR file1 file2 file3 file4 BAR

me$ set -f
me$ echo $FOO
BAR * BAR

me$ set +f
me$ GLOBIGNORE=*
me$ echo $FOO
BAR * BAR

4
দুর্দান্ত ব্যাখ্যা, ধন্যবাদ! আমার ইউজকেসটি হ'ল SELECT * FROM etc.এটিই একমাত্র উপায়।
নটোল

1
সেট -f সমাধান উপস্থাপনের জন্য ধন্যবাদ!
হাচরে

5
FOO='BAR * BAR'
echo "$FOO"

এটি কাজ করে তবে প্রথম লাইনে একক উদ্ধৃতিগুলি ডাবল কোটে পরিবর্তন করা অপরিহার্য নয়।
ফিনিউ

1
না, এটি নয়, আপনি যখন একটি বিশেষ শেল অক্ষর অন্তর্ভুক্ত করতে যাচ্ছেন এবং আপনি কোনও প্রতিস্থাপন চান না তখন একক উদ্ধৃতি ব্যবহার করার অভ্যাসটি আরও ভাল।
tzot


3

এটি printfবরং echoকমান্ড লাইনে ব্যবহার করার অভ্যাসে প্রবেশের উপযুক্ত হতে পারে ।

এই উদাহরণে এটি খুব বেশি সুবিধা দেয় না তবে আরও জটিল আউটপুট সহ এটি আরও কার্যকর হতে পারে।

FOO="BAR * BAR"
printf %s "$FOO"

নরকে কেন? প্রিন্টফ একটি পৃথক প্রক্রিয়া (কমপক্ষে, কোনও অন্তর্নির্মিত ব্যাশ নয়) এবং আপনি যে মুদ্রণটি প্রদর্শন করেন তাতে প্রতিধ্বনিতে কোনও লাভ নেই।
ডিডিএ

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