বাশ-এ-শর্তে নিয়মিত এক্সপ্রেশন ব্যবহার করুন


88

আমি অবাক হয়েছি নিয়মিত অভিব্যক্তিটি ব্যবহার করার জন্য সাধারণ নিয়মটি যদি ব্যাশে ক্লজ থাকে?

এখানে একটি উদাহরণ

$ gg=svm-grid-ch  
$ if [[ $gg == *grid* ]] ; then echo $gg; fi  
svm-grid-ch  
$ if [[ $gg == ^....grid* ]] ; then echo $gg; fi  
$ if [[ $gg == ....grid* ]] ; then echo $gg; fi  
$ if [[ $gg == s...grid* ]] ; then echo $gg; fi  
$   

কেন শেষ তিনটি ব্যর্থ হয়?

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

উত্তর:


129

গ্লোব প্যাটার্ন ব্যবহার করার সময়, একটি প্রশ্ন চিহ্ন একটি একক অক্ষরকে উপস্থাপন করে এবং একটি নক্ষত্রটি শূন্য বা আরও বেশি অক্ষরের ক্রম উপস্থাপন করে:

if [[ $gg == ????grid* ]] ; then echo $gg; fi

নিয়মিত অভিব্যক্তি ব্যবহার করার সময়, বিন্দুটি একটি একক অক্ষরকে উপস্থাপন করে এবং একটি নক্ষত্রটি শূন্য বা পূর্বের বর্ণের আরও অনেক কিছু উপস্থাপন করে। সুতরাং " .*" শূন্য বা যেকোন চরিত্রের আরও প্রতিনিধিত্ব করে, " a*" শূন্য বা আরও "a", " [0-9]*" শূন্য বা আরও সংখ্যার প্রতিনিধিত্ব করে। অন্য দরকারী একটি (অনেকের মধ্যে) হ'ল পূর্ব চিহ্নটি যা এক বা একাধিক চরিত্রকে উপস্থাপন করে plus সুতরাং " [a-z]+" এক বা একাধিক ছোট হাতের আলফা চরিত্র উপস্থাপন করে (সি লোকালে - এবং কিছু অন্যান্য)।

if [[ $gg =~ ^....grid.*$ ]] ; then echo $gg; fi

স্ট্রিং মেলানোর দুটি উপায় আছে: গ্লোব প্যাটার্ন এবং নিয়মিত প্রকাশ? গ্লোব পেট্রনগুলি কেবল ফাইলের নামের জন্যই ব্যবহৃত হয় না? ব্যাশে, কখন গ্লোব প্যাটার্ন ব্যবহার করবেন এবং কখন নিয়মিত এক্সপ্রেশন ব্যবহার করবেন? ধন্যবাদ!
টিম

4
@ টিম: বাশ এর বেশিরভাগ বা সমস্ত সংস্করণে গ্লোববিং উপলব্ধ। রেজেক্সের মিলটি কেবলমাত্র 3 এবং ততোধিক সংস্করণে উপলভ্য, তবে আমি কেবল এটি 3.2 এবং তারপরে ব্যবহার করার পরামর্শ দিই। রেজেক্সেস গ্লোব্বিংয়ের চেয়ে অনেক বেশি বহুমুখী।
ডেনিস উইলিয়ামসন


14
if [[ $gg =~ ^....grid.* ]]

4
আপনার "...." এর পরিবর্তে "। {4}" ব্যবহার করতে সক্ষম হওয়া উচিত, অর্থাত "^। {4} গ্রিড। *"। এটি পড়া এবং বোঝা আরও সহজ হতে পারে।
ব্যবহারকারী 276648

8

আরও বহনযোগ্য সমাধানে আগ্রহী ব্যক্তিদের জন্য এই সমাধানটি grepএবং বেসিক shবিল্টইনগুলি যুক্ত করা ( bashসংস্করণের তুলনায় স্বতন্ত্র ; shলিনাক্স নন প্ল্যাটফর্মগুলিতে সাধারণ পুরানো সাথেও কাজ করে))

# GLOB matching
gg=svm-grid-ch    
case "$gg" in
   *grid*) echo $gg ;;
esac

# REGEXP    
if echo "$gg" | grep '^....grid*' >/dev/null ; then echo $gg ; fi    
if echo "$gg" | grep '....grid*' >/dev/null ; then echo $gg ; fi    
if echo "$gg" | grep 's...grid*' >/dev/null ; then echo $gg ; fi    

# Extended REGEXP
if echo "$gg" | egrep '(^....grid*|....grid*|s...grid*)' >/dev/null ; then
  echo $gg
fi    

কিছু grepঅবতারগুলি -q(নিঃশব্দ) বিকল্পকে পুনঃনির্দেশের বিকল্প হিসাবে সমর্থন করে /dev/nullতবে পুনর্নির্দেশটি আবার সর্বাধিক বহনযোগ্য is


egrep

4
grep -qপরিবর্তে ব্যবহার করুন grep >/dev/null
bfontaine

3

@ ওপ,

গ্লোব পেট্রনগুলি কেবল ফাইলের নামের জন্যই ব্যবহৃত হয় না?

না, "গ্লোব" প্যাটার্নটি কেবল ফাইলের নামের জন্যই ব্যবহৃত হয় না। আপনি স্ট্রিংগুলির সাথে তুলনা করতে এটি ব্যবহার করেন। আপনার উদাহরণগুলিতে, আপনি স্ট্রিংগুলির নিদর্শনগুলির জন্য কেস / এস্যাক ব্যবহার করতে পারেন।

 gg=svm-grid-ch 
 # looking for the word "grid" in the string $gg
 case "$gg" in
    *grid* ) echo "found";;
 esac

 # [[ $gg =~ ^....grid* ]]
 case "$gg" in ????grid*) echo "found";; esac 

 # [[ $gg =~ s...grid* ]]
 case "$gg" in s???grid*) echo "found";; esac

ব্যাশে, কখন গ্লোব প্যাটার্ন ব্যবহার করবেন এবং কখন নিয়মিত এক্সপ্রেশন ব্যবহার করবেন? ধন্যবাদ!

রেগেক্স "গ্লোব প্যাটার্নগুলি" এর তুলনায় আরও বহুমুখী এবং "সুবিধাজনক", তবে আপনি যদি এমন জটিল কাজগুলি না করেন যা "গ্লোব্বিং / এক্সটেন্ডেড গ্লোব্বিং" সহজেই সরবরাহ করতে না পারে, তবে রেজেেক্স ব্যবহার করার দরকার নেই। রেগেক্স বাশ <3.2 (ডেনিস হিসাবে উল্লিখিত) সংস্করণে সমর্থিত নয়, তবে আপনি এখনও বর্ধিত গ্লোব্বিং ব্যবহার করতে পারেন (সেট করে extglob)। বর্ধিত globbing জন্য, দেখুন এখানে এবং কিছু সহজ উদাহরণ এখানে

ওপি-র জন্য আপডেট: উদাহরণস্বরূপ, দুটি অক্ষর (বিন্দু "।" মানে 1 চর) দিয়ে শুরু হওয়া ফাইলগুলি খুঁজে বের করার পরে রেজেক্স ব্যবহার করে "জি" অনুসরণ করা হবে

যেমন আউটপুট

$ shopt -s dotglob
$ ls -1 *
abg
degree
..g

$ for file in *; do [[ $file =~ "..g" ]] && echo $file ; done
abg
degree
..g

উপরের দিকে, ফাইলগুলি মিলছে কারণ তাদের নামগুলিতে "জি" এর পরে দুটি অক্ষর রয়েছে। (অর্থাত্ ..g)

গ্লোব্বিংয়ের সমতুল্য এই জাতীয় কিছু হবে: ( অর্থের জন্য রেফারেন্সটি দেখুন ?এবং *)

$ for file in ??g*; do echo $file; done
abg
degree
..g

ধন্যবাদ ঘোস্টডগ .৪। ৩.২ এর চেয়ে বেশি সংস্করণযুক্ত বাশ-এ, যেদিকে যেখানে প্রদর্শিত হবে সেখানে নিয়মিত ভাব প্রকাশ করা যাবে? বা নিয়মিত ভাবটি কেবল কিছু বিশেষ পরিস্থিতিতে ব্যবহার করা যেতে পারে? উদাহরণস্বরূপ, আমি দেখেছি যে "ls ?? g" কাজ করছে যখন "ls ..g" হয় না।
টিম

দরকার পড়লে রেইগেক্স ব্যবহারের জন্য আপনাকে থামাতে হবে না। এটা আপনার উপর নির্ভর করছে. দ্রষ্টব্য, রেজেক্স সিনট্যাক্স শেল গ্লোববিং সিনট্যাক্স থেকে পৃথক। সুতরাং ls ..gকাজ করে না। আপনি শেলটিকে বলছেন যে নামযুক্ত একটি ফাইল সন্ধান করতে ..g। Regex সিনট্যাক্স সম্পর্কে জানতে হিসাবে, আপনি চেষ্টা করতে পারেন perldoc perlretut, perldoc perlrequickঅথবা কোনো না info sedকমান্ড লাইন।
ghostdog74
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.