কেন বিশ্বব্যাপী প্যাটার্নে `| lite আক্ষরিক আচরণ করা হচ্ছে না?


13

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

  1. কেন একটি ত্রুটি আছে:

    $ [[ $a = a|b ]]  
    bash: syntax error in conditional expression: unexpected token `|'
    bash: syntax error near `|b'

    [[ ... ]]দ্বিতীয় অপারেন্ডের অভ্যন্তরে =গ্লোববিং প্যাটার্ন হবে বলে আশা করা হচ্ছে।

    কি a|bএকটি বৈধ globbing প্যাটার্ন নয়? আপনি কোন সিনট্যাক্স বিধি লঙ্ঘন করে তা চিহ্নিত করতে পারেন?

  2. নীচে কিছু মন্তব্য পয়েন্ট আউট যে |পাইপ হিসাবে ব্যাখ্যা করা হয়।

    তারপর পরিবর্তন =করার জন্য উল্লিখিত glob প্যাটার্ন জন্য =~Regex প্যাটার্ন করতে জন্য |কাজ

    $ [[ $a =~ a|b ]]

    আমি শিখেছি থেকে শিক্ষণ ব্যাশ মধ্যে p180 আমার আগের পোস্ট যে |ব্যাখ্যার শুরুতে নল হিসাবে স্বীকৃত হয়, ব্যাখ্যা অন্য কোন পদক্ষেপ (উদাহরণ মধ্যে শর্তসাপেক্ষ এক্সপ্রেশন পার্স সহ) এমনকি আগে। সুতরাং |যখন =~অবৈধ ব্যবহারে পাইপ হিসাবে স্বীকৃতি না পেয়ে ব্যবহার করার সময় কীভাবে রেজেক্স অপারেটর হিসাবে স্বীকৃতি দেওয়া যায় =? এটি আমাকে ভাবায় যে অংশ 1 এর বাক্য গঠন ত্রুটির অর্থ এই নয় যে |এটি পাইপ হিসাবে ব্যাখ্যা করা হয়েছে।

    শেল স্ট্যান্ডার্ড ইনপুট বা স্ক্রিপ্ট থেকে প্রতিটি লাইনকে পাইপলাইন বলে; এতে শূন্য বা আরও বেশি পাইপ অক্ষর (|) দ্বারা পৃথক করা এক বা একাধিক কমান্ড রয়েছে। এটি পড়ার প্রতিটি পাইপলাইনের জন্য, শেল এটি কমান্ডগুলিতে বিভক্ত করে, পাইপলাইনের জন্য I / O সেটআপ করে, তারপরে প্রতিটি কমান্ডের জন্য নিম্নলিখিতটি করে (চিত্র 7-1):

ধন্যবাদ।


1
নোট করুন যে ব্যাশের কয়েকটি সংস্করণে এক্সটগ্লোব পার্সিং (যেখানে |বিশেষ) এর ডানদিকে ডানদিকে ডিফল্টরূপে চালু রয়েছে [[ $var = $pattern ]]। সংস্করণ এবং shoptবিকল্প কনফিগারেশনগুলি যেখানে এই আচরণটি দেখা যায় তা বিচ্ছিন্ন করা আকর্ষণীয় হবে - যদি কেবল এটিই থাকে যেখানে extglobডিফল্ট বা স্পষ্টরূপে কনফিগারেশন অনুসারে হয়, তবে আমরা সেখানে আছি।
চার্লস ডাফি

2
বিটিডাব্লু, আপনি যদি পাইপ চরিত্রটিকে পার্সিংয়ের পূর্ববর্তী পর্যায়ে হস্তক্ষেপের ক্ষেত্রে কিছুটা আরও বিস্তৃতভাবে রায় দিতে চান (যা আমি সম্মত হই তবে তা ঘটছে না, তবে এটি পাঠকের কাছে এতটা সুস্পষ্ট নয়), আপনি চাইতেন ব্যবহার করুন pattern='a|b'এবং তারপরে $patternআরএইচএসে অনাবৃত প্রসারিত করুন।
চার্লস ডাফি

@CharlesDuffy, যে বিন্দু ছিল তৈরি করা হচ্ছে Q & A- যা এই প্রশ্নটি একটি ফলো-আপ হয়।
স্টাফেন চেজেলাস

আহ - প্রসঙ্গটি বোঝায়; এবং আপনার উত্তর এখানে অসামান্য। উভয় বিবেচনার জন্য আপনাকে ধন্যবাদ।
চার্লস ডাফি 15

টিম, নীচের উত্তরগুলির মধ্যে ডিজেড আপনার প্রশ্নের উত্তর দিয়েছেন? যদি তা হয় তবে তা গ্রহণ করার বিষয়টি বিবেচনা করুন। ধন্যবাদ!
জেফ শ্যাচলার

উত্তর:


13

এর কোনও ভাল কারণ নেই

[[ $a = a|b ]]

$ a|bA স্ট্রিং কিনা তা পরীক্ষা করার পরিবর্তে একটি ত্রুটির প্রতিবেদন করা উচিত , যখন [[ $a =~ a|b ]]ত্রুটি ফিরে আসে না।

একমাত্র কারণ হ'ল |সাধারণত (বাইরে এবং ভিতরে [[ ... ]]) একটি বিশেষ চরিত্র। সেই [[ $a =অবস্থানে, এমন bashএক ধরণের টোকেন প্রত্যাশা করে যা একটি সাধারণ শেল কমান্ড লাইনে আর্গুমেন্ট বা পুনর্নির্দেশগুলির লক্ষ্যগুলির মতো একটি সাধারণ ডাব্লুআরআরড (তবে যেন extglobবাশ ৪.১-এর পরে বিকল্পটি সক্ষম হয়েছে)।

( এখানে ওয়ার্ড দ্বারা , আমি পোসিক্স স্পেসিফিকেশন দ্বারা বর্ণিত মতকল্পিত শেল ব্যাকরণে একটি শব্দের উল্লেখ করি , এটি এমন কিছু যা শেল একটি সাধারণ শেল কমান্ড লাইনে একটি টোকেন হিসাবে বিভক্ত হবে, ইংরেজির মতো শব্দের সংজ্ঞা নয়) অক্ষর একটি অনুক্রম বা অ- ব্যবধান বর্ণের একটি ক্রম। এক foo"bar baz", $(echo x y)এই ধরনের দুটি শব্দ গুলি)।

একটি সাধারণ শেল কমান্ড লাইনে:

echo a|b

অর্থাৎ echo aজন্য বাঁশি বাজালাম ba|bএকটি ওয়ার্ড নয় , এটি তিনটি টোকেন: একটি a ওয়ার্ড , একটি |টোকেন এবং একটি b ওয়ার্ড টোকেন।

এটি ব্যবহার করার সময় [[ $a = a|b ]], bashকোনও ওয়ার্ডটি প্রত্যাশা করে যা এটি পায় ( a), তবে তারপরে একটি অপ্রত্যাশিত |টোকেন পাওয়া যায় যা ত্রুটির কারণ হয়।

মজার বিষয়, এতে bashঅভিযোগ করবেন না:

[[ $a = a||b ]]

কারণ এটি এখন একটি aটোকেন এবং তার পরে একটি ||টোকেন রয়েছে b, সুতরাং এটি একইভাবে পার্স করা হয়েছে:

[[ $a = a || b ]]

কোনটি পরীক্ষা করছে যে $aহয় aবা যে bস্ট্রিং খালি নয় এমন।

এখন:

[[ $a =~ a|b ]]

bashএকই পার্সিং বিধি থাকতে পারে না। একই পার্সিং বিধিটি থাকা মানে এই হবে যে উপরেরটি একটি ত্রুটি দেয় এবং এটির জন্য একটি একক ওয়ার্ড| নিশ্চিত a|bকরা দরকার । তবে, বাশ ৩.২ থেকে আপনি যদি এটি করেন:

[[ $a =~ 'a|b' ]]

এটি আর a|bরেজিএক্সএক্সের বিপক্ষে নয় বরং রেজিপ্সপের বিপরীতে মিলছে a\|b। এটি হ'ল শেল কোটিংয়ের রেজিএক্সএক্স অপারেটরগুলির বিশেষ অর্থ সরিয়ে দেওয়ার পার্শ্ব প্রতিক্রিয়া রয়েছে। এটি একটি বৈশিষ্ট্য, তাই আচরণটি [[ $a = "?" ]]একটির অনুরূপ , তবে ওয়াইল্ডকার্ড নিদর্শনগুলি (ব্যবহৃত হয় [[ $a = pattern ]]) হ'ল শেল ওয়ার্ডস (উদাহরণস্বরূপ গ্লোবগুলিতে ব্যবহৃত হয়), যখন রেজিেক্সপস হয় না।

সুতরাং bashসব বর্ধিত regexp অপারেটার অন্যথায় স্বাভাবিকভাবে মত বিশেষ শেল অক্ষর আচরণ করা হয়েছে |, (, )ভিন্নভাবে যখন একটি আর্গুমেন্ট পার্স =~অপারেটর।

তবুও, লক্ষ্য করুন যে

 [[ $a =~ (ab)*c ]]

এখন কাজ করে,

 [[ $a =~ [)}] ]]

না। তোমার দরকার:

 [[ $a =~ [\)}] ]]
 [[ $a =~ [')'}] ]]

পূর্ববর্তী সংস্করণগুলির মধ্যে bashযা ব্যাকস্ল্যাশের সাথে ভুলভাবে মেলে। যে এক স্থির ছিল, কিন্তু

 [[ $a =~ [^]')'] ]]

না না মত উদাহরণস্বরূপ উচিত ব্যাকস্ল্যাশ উপর মেলে। কারণ বন্ধনীগুলির মধ্যে রয়েছে bashতা উপলব্ধি করতে ব্যর্থ হয় ), তাই )কোনও [^]\)]রেজপ্লেক্সের ফলস্বরূপ পালিয়ে যায় যা কোনও চরিত্রের সাথে মেলে তবে ], \এবং )

ksh93 যে ফ্রন্টে আরও খারাপ বাগ আছে।

ইন zsh, এটি একটি সাধারণ শেল শব্দ যা প্রত্যাশা করা হয় এবং রেজিএক্সএক্স অপারেটরদের উদ্ধৃতি দিয়ে রেজিএক্সএক্স অপারেটরদের অর্থ প্রভাবিত করে না।

[[ $a =~ 'a|b' ]]

মিলছে a|bরেজিপ্স্পের বিপরীতে ।

তার মানে কমান্ডটি / কমান্ডে =~যুক্ত করা যেতে পারে :[test

[ "$a" '=~' 'a|b' ]
test "$a" '=~' 'a|b'

(এছাড়াও কাজ yash=~চাহিদা উদ্ধৃত করা zshযেমন =somethingএকটি বিশেষ শেল অপারেটর যায়)।

bash 3.1 এর মতো আচরণ করত zsh। এটি ৩.২-এ পরিবর্তিত হয়েছিল, সম্ভবত এটির সাথে সারিবদ্ধ হওয়ার জন্য ksh93(যদিও bashশেলটি প্রথমে উপস্থিত হয়েছিল [[ =~ ]]) তবে আপনি এখনও করতে BASH_COMPAT=31বা shopt -s compat31পূর্ববর্তী আচরণে [[ $a =~ a|b ]]ফিরে যেতে পারেন ( bash৩.১-এ ত্রুটি ফিরে আসার পরে তা আর হয় না) এর bash -O compat31নতুন সংস্করণ সহ bash)।

আশা করি এটি স্পষ্ট হয়েছে যে আমি কেন নিয়মগুলি বিভ্রান্তিকর বলেছিলাম এবং কেন ব্যবহার করছি:

[[ $a =~ $var ]]

অন্যান্য শেলগুলির বহনযোগ্যতা সহ সহায়তা করে।


zsh এছাড়াও একটি ত্রুটি রিপোর্ট করছে [[ $a = a|b ]]
নটঅনিক্সনাজি

@ আইসাক, হ্যাঁ, আমি এখানে এটি তৈরি করছি। a|bএকটি শেল নয় বাক্য এখানে এটা a, |এবং bটোকেন। যেমন echo a|bআউটপুট দেয় না a|bবা a|bগ্লোব প্রসারিত হয় না , আপনাকে উদ্ধৃত করতে হবে যে |এটি একটি বিশেষ শেল চরিত্র যা সেই প্রসঙ্গে অবৈধ। [[ $a = (a|b) ]]হায় কাজ ভালো echo (a|b)যেমন কাজ করবে (a|b)একটি zsh ওয়াইল্ডকার্ড অপারেটর।
স্টাফেন চেজেলাস

আপনার উত্তরের শব্দ এবং ব্যাখ্যা কেবল নাম বাশ। এটি পুরো সত্য নয়।
নোটঅনিক্সনাজি

11

স্ট্যান্ডার্ড globs ( "ফাইলের নাম সম্প্রসারণ") হল: *, ?, এবং [ ... ]|স্ট্যান্ডার্ড (অ-এক্সটগ্লোব) সেটিংসে কোনও বৈধ গ্লোব অপারেটর নয়।

চেষ্টা করুন:

shopt -s extglob
[[ a = @(a|b) ]] && echo matched

1
ধন্যবাদ। কিন্তু কেন |আক্ষরিকভাবে আগ্রহী নয়? কেন একটি সিনট্যাক্স ত্রুটি আছে?
টিম

1
এটি উদ্ধৃত হয়নি।
জেফ শ্যাচলার

3
স্ট্যান্ডার্ড সেটিংসে, |কোনও গ্লোব অপারেটর নয়, তাই |উদ্ধৃত না করে আক্ষরিক অর্থে ব্যাখ্যা করা যায় না ? সুতরাং কেন একটি সিনট্যাক্স ত্রুটি আছে?
টিম

1
|একটি নিয়ন্ত্রণ চরিত্র; এটি কখনই কোনও অক্ষর বা সংখ্যা হিসাবে একইভাবে আক্ষরিক চরিত্র হিসাবে বিবেচিত হয় না।
চিপনার

3
কারণ সেই মোডে শেলটি এখনও-বন্ধ-বন্ধ [[]] এর মাঝামাঝি কোনও পাইপ পুনর্নির্দেশ চরিত্রের প্রত্যাশা করে না। [[ $a = aকোনও বৈধ কমান্ড নয় যার আউটপুট অন্য প্রক্রিয়াতে পাইপ করা যেতে পারে (কমপক্ষে শেলটি ভেবেছিল আপনি যা করার চেষ্টা করছেন)।
জেসন সি

5

আপনি যদি একটি রেজেক্স ম্যাচ চান তবে পরীক্ষাটি হ'ল:

[[ "$a" =~ a|b ]]

@ টিম আপনার নতুন প্রশ্ন খোলার উচিত, ক্রমাগত আপনার বর্তমান প্রশ্ন সম্পাদনা করা উচিত নয়।
উদ্যানক্ষেত্র

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