বাশ-এর ​​একটি কমান্ডের মধ্যে একক উদ্ধৃতিগুলির মধ্যে ভেরিয়েবলের প্রসারণ


393

আমি বাশ স্ক্রিপ্ট থেকে একটি কমান্ড চালাতে চাই যেখানে সিঙ্গল কোটস এবং ভেরিয়েবলের ভিতরে সিঙ্গল কোটস এবং কিছু অন্যান্য কমান্ড রয়েছে।

যেমন repo forall -c '....$variable'

এই বিন্যাসে, $পালানো হয় এবং ভেরিয়েবল প্রসারিত হয় না।

আমি নিম্নলিখিত বৈচিত্রগুলি চেষ্টা করেছিলাম কিন্তু সেগুলি প্রত্যাখ্যান করা হয়েছিল:

repo forall -c '...."$variable" '

repo forall -c " '....$variable' "

" repo forall -c '....$variable' "

repo forall -c "'" ....$variable "'"

আমি যদি ভেরিয়েবলের পরিবর্তে মানটি পরিবর্তন করি তবে কমান্ডটি ঠিক জরিমানা করা হবে।

দয়া করে বলুন আমি কোথায় ভুল করছি।


33
repo forall -c ' ...before... '"$variable"' ...after...'
এন। 'সর্বনাম' মি।

2
@ এনএম এর একক উদ্ধৃতি রেপো কমান্ডের একটি অংশ। আমি মনে করি এটি কাজ করবে না
রচিত

1
bashএকক উদ্ধৃতি খাওয়া। হয় আপনি প্রবেশ করছেন না bash, অথবা একক উদ্ধৃতি repoকমান্ডের অংশ নয় ।
এন। 'সর্বনাম' মি।

আমি আপনাকে পেয়েছি তা নিশ্চিত নই, তবে যদি একক উদ্ধৃতিগুলি পাওয়া দরকার থাকে তবে ফোরাল-সি "'... এর আগে ..." $ ভেরিয়েবল "... পরে ...'" কাজ করবেন না?
ecv

এটি একটি বাশ স্ক্রিপ্ট ব্যাশ শেল এবং রেপো ফোরাল কমান্ডে চলমান একক উদ্ধৃতিতে পরামিতি নেয় takes যদি আমি আসল মানটি প্রতিস্থাপন করি তবে কমান্ডটি ঠিকঠাক হবে runs
রচিত

উত্তর:


621

একক উদ্ধৃতিগুলির ভিতরে সমস্ত কিছুই আক্ষরিক অর্থে সংরক্ষণ করা হয়, ব্যতিক্রম ছাড়াই।

এর অর্থ আপনাকে উদ্ধৃতিগুলি বন্ধ করতে হবে, কিছু সন্নিবেশ করতে হবে এবং তারপরে আবার প্রবেশ করতে হবে।

'before'"$variable"'after'
'before'"'"'after'
'before'\''after'

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

শেল দ্বারা ব্যাখ্যা করা স্ট্রিংগুলি সংযুক্ত না করে

ভেরিয়েবলগুলি একত্রিত করে আপনার শেল কমান্ডগুলি একেবারে এড়ানো উচিত। এটি এসকিউএল টুকরা (এসকিউএল ইনজেকশন!) এর সমাহারের অনুরূপ একটি খারাপ ধারণা।

সাধারণত কমান্ডে স্থানধারক থাকা এবং ভেরিয়েবলের সাথে কমান্ড একসাথে সরবরাহ করা সম্ভব হয় যাতে আহ্বানকারীদের আবেদনের যুক্তি তালিকা থেকে তাদের গ্রহণ করা যায়।

উদাহরণস্বরূপ, নিম্নলিখিতটি খুব নিরাপদ। এটি করবেন না

script="echo \"Argument 1 is: $myvar\""
/bin/sh -c "$script"

বিষয়বস্তু $myvarযদি অবিশ্বস্ত হয় তবে এখানে একটি শোষণ দেওয়া আছে:

myvar='foo"; echo "you were hacked'

উপরোক্ত অনুরোধের পরিবর্তে অবস্থানগত আর্গুমেন্ট ব্যবহার করুন। নিম্নলিখিত অনুরোধটি আরও ভাল - এটি শোষণযোগ্য নয়:

script='echo "arg 1 is: $1"'
/bin/sh -c "$script" -- "$myvar"

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


@ জো.এসও যে কাজ করবে না। কারণ প্রথম উক্তি বন্ধ হওয়া পর্যন্ত রেপো কমান্ড কেবলমাত্র পরামিতিগুলি নেবে। এরপরের যে কোনও কিছু রেপোর জন্য উপেক্ষা করা হবে এবং অন্য একটি ত্রুটি উত্পন্ন করবে।
রচিত

8
@ রচিত - শেলটি এর মতো কাজ করে না। "some"thing' like'thisসমস্ত শেল শেল। পার্সিং সম্পর্কিত যতটুকু উদ্ধৃতি চিহ্নগুলি কোনও কিছুর অবসান ঘটায় না, এবং শেল দ্বারা আহ্বানিত কোনও আদেশের উপায় নেই যে কীভাবে উদ্ধৃত হয়েছিল তা বলার জন্য।
মার্ক রিড

3
এই দ্বিতীয় বাক্যটি ("আপনি একক উদ্ধৃতি থেকেও বাঁচতে পারবেন না") শেলের ব্ল্যাকহোলগুলির একক উদ্ধৃতি তৈরি করে।

@ এভার্ট: কীভাবে এটি আরও ভাল বলা যায় তা জানেন না। আমি বাক্যটি সরিয়েছি
জো সো

@ জোসো এটি লজ্জাজনক: কোনও রসিকতা সমতল হয় না।

96

repoকমান্ড গ্রাহ্য না করতে কোট কি ধরনের পায়। আপনার যদি প্যারামিটার সম্প্রসারণ প্রয়োজন হয় তবে ডাবল উদ্ধৃতি ব্যবহার করুন। যদি এর অর্থ হল যে আপনি প্রচুর স্টাফ ব্যাকস্ল্যাশ করে চলেছেন তবে এর বেশিরভাগটির জন্য একক উদ্ধৃতি ব্যবহার করুন এবং তারপরে বিচ্ছিন্ন হয়ে the অংশটির দ্বিগুণ হয়ে যান যেখানে আপনার সম্প্রসারণের প্রয়োজন।

repo forall -c 'literal stuff goes here; '"stuff with $parameters here"' more literal stuff'

আপনার আগ্রহী হলে ব্যাখ্যা অনুসরণ করে।

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

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

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

echo \"Thank\ you.\ \ That\'ll\ be\ \$4.96,\ please,\"\ said\ the\ cashier

... এটি ক্লান্তিকর হতে পারে। শেলটি একটি বিকল্প প্রস্তাব করে: উদ্ধৃতি চিহ্নগুলি। এগুলি দুটি প্রধান জাতের মধ্যে আসে।

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

echo "\"Thank you. That'll be \$4.96, please,\" said the cashier"

একক-উদ্ধৃতি চিহ্নগুলি আরও কঠোর। তাদের মধ্যে সমস্ত কিছুই ব্যাকস্ল্যাশ সহ পুরোপুরি আক্ষরিক অর্থে নেওয়া হয়। একক উদ্ধৃতিতে আক্ষরিক একক উদ্ধৃতি পাওয়ার কোনও উপায় নেই।

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

echo '"Thank you. That'\''ll be $4.96, please," said the cashier'

সুতরাং এটি সহজ - অনেক কম ব্যাকস্ল্যাশস, যদিও ক্লোজ-সিঙ্গল-কোট, ব্যাকস্ল্যাশড-আক্ষরিক-একক-উদ্ধৃতি, ওপেন-সিঙ্গল-কোট ক্রমটি কিছুটা অভ্যস্ত হয়ে উঠবে।

আধুনিক শেলগুলি পসিক্স স্ট্যান্ডার্ড দ্বারা নির্দিষ্ট না করে আরও একটি উদ্ধৃতি শৈলী যুক্ত করেছে, যেখানে শীর্ষস্থানীয় একক উদ্ধৃতি চিহ্নটি ডলারের চিহ্ন সহ উপস্থাপিত হয়েছে। স্ট্রিংগুলি উদ্ধৃত এএনএসআই সি প্রোগ্রামিং ভাষায় স্ট্রিং লিটারেলের অনুরূপ কনভেনশন অনুসরণ করে এবং তাই কখনও কখনও "এএনএসআই স্ট্রিংস" এবং $'... 'জোড় "এএনএসআই কোটস" নামে পরিচিত। এই ধরনের স্ট্রিংগুলির মধ্যে, ব্যাকস্ল্যাশগুলি সম্পর্কে আক্ষরিকভাবে গ্রহণের উপরের পরামর্শটি আর কার্যকর হয় না। পরিবর্তে, তারা আবার বিশেষ হয়ে ওঠে - আপনি কেবল এটির ব্যাকস্ল্যাশ প্রিডিং করে কেবল আক্ষরিক একক উদ্ধৃতি চিহ্ন বা ব্যাকস্ল্যাশকে অন্তর্ভুক্ত করতে পারবেন না, তবে শেলটি এএনএসআই সি অক্ষরটি পলায়নের প্রসারকেও প্রসারিত করে ( \nনতুন লাইনের \tজন্য, ট্যাবের \xHHজন্য এবং অক্ষরের সাথে অক্ষরের জন্য) হেক্সাডেসিমাল কোডHH)। অন্যথায়, তারা একক-উদ্ধৃত স্ট্রিং হিসাবে আচরণ করে: কোনও প্যারামিটার বা কমান্ড প্রতিস্থাপন হয় না:

echo $'"Thank you.  That\'ll be $4.96, please," said the cashier'

গুরুত্বপূর্ণ বিষয়টি লক্ষ্যণীয় হ'ল echoকমান্ডের যুক্তি হিসাবে একক স্ট্রিংটি পাওয়া গেছে এই উদাহরণগুলির মধ্যে একই is শেলটি একটি কমান্ড লাইনের পার্সিং করার পরে, কমান্ডটি চালিত হওয়ার উপায় নেই যে কীভাবে উদ্ধৃত হয়েছিল। এমনকি যদি এটি চেয়েছিল।


2
হ্যাঁ. আমি এখন বুঝতে পেরেছি. এটি পুরোপুরি কাজ করে। আপনার সাহায্যের জন্য অসংখ্য ধন্যবাদ!
রচিত

6
এই উত্তরটি দুর্দান্ত ছিল।
ভিনসিয়াস ফেরেওো

1
$'string'POSIX বিন্যাসটি কি সামঞ্জস্যপূর্ণ? এছাড়াও, এর কোনও নাম আছে?
ওয়াইল্ডকার্ড

2
@ উইল্ডকার্ড $'string'একটি নন- পসিক্স এক্সটেনশন, যা আমি "এএনএসআই স্ট্রিং" হিসাবে উল্লেখ করেছি; আমি এই তথ্যগুলিকে উত্তরে অন্তর্ভুক্ত করেছি। এই জাতীয় স্ট্রিংগুলি বেশিরভাগ আধুনিক বোর্ন-সামঞ্জস্যপূর্ণ শেলগুলিতে কাজ করে: বাশ, ড্যাশ, কেএসএইচ (উভয় এটিএন্ডটি এবং পিডি), এবং zsh সমস্ত তাদের সমর্থন করে।
মার্ক রিড

1
পিছনে লিঙ্ক করুন - কমান্ড লাইনের যুক্তিতে কোন অক্ষরগুলি এড়িয়ে চলতে হবে? ইউনিক্স এবং লিনাক্স স্ট্যাক এক্সচেঞ্জ এ।
ওয়াইল্ডকার্ড

3

নীচে আমার জন্য কী কাজ করেছে -

QUOTE="'"
hive -e "alter table TBL_NAME set location $QUOTE$TBL_HDFS_DIR_PATH$QUOTE"

2
আমি আশা করি টিবিএল_এইচডিএফএস_ডির_প্যাথটি ব্যবহারকারী প্রদত্ত ইনপুট বিটিডব্লিউ নয়, এটি একটি সুন্দর
স্কয়ার

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

2

সম্পাদনা: (প্রশ্নের মন্তব্য অনুযায়ী :)

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


আপনার সাহায্যের জন্য কেভিন ধন্যবাদ।
রচিত

2

শুধু প্রিন্টফ ব্যবহার করুন

পরিবর্তে

repo forall -c '....$variable'

প্রসারিত টোকেনটি প্রসারিত ভেরিয়েবলের সাথে প্রতিস্থাপন করতে প্রিন্টফ ব্যবহার করুন।

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

template='.... %s'

repo forall -c $(printf "${template}" "${variable}")

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

0

চলকগুলিতে একক উদ্ধৃতি থাকতে পারে।

myvar=\'....$variable\'

repo forall -c $myvar

তারা পারে, তবে এটি করার সঠিক উপায় নয় - আপনার এখনও "$myvar"ডাবল উদ্ধৃতি দেওয়া উচিত ।
ট্রিপলি

-2

এটি কি তোমার জন্য কাজ করে?

eval repo forall -c '....$variable'

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