दशा में अगर-हालत में नियमित अभिव्यक्ति का उपयोग करें


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  
$   

आखिरी तीन मैच क्यों नहीं हो पाए?

आशा है कि आप इस उदाहरण के लिए नहीं, जितना संभव हो उतने सामान्य नियम दे सकते हैं।

जवाबों:


128

ग्लोब पैटर्न का उपयोग करते समय, एक प्रश्न चिह्न एक एकल वर्ण का प्रतिनिधित्व करता है और एक तारांकन शून्य या अधिक वर्णों के अनुक्रम का प्रतिनिधित्व करता है:

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

एक नियमित अभिव्यक्ति का उपयोग करते समय, एक बिंदु एकल वर्ण का प्रतिनिधित्व करता है और एक तारांकन पूर्ववर्ती चरित्र के शून्य या अधिक का प्रतिनिधित्व करता है। तो " .*" किसी भी वर्ण के शून्य या अधिक का a*प्रतिनिधित्व करता है , " " शून्य या अधिक "a [0-9]*" का प्रतिनिधित्व करता है , " " शून्य या अधिक अंकों का प्रतिनिधित्व करता है। एक और उपयोगी एक (कई के बीच) प्लस चिन्ह है जो पूर्ववर्ती चरित्र में से एक या अधिक का प्रतिनिधित्व करता है। तो " [a-z]+" एक या अधिक लोअरकेस अल्फा चरित्र (सी लोकेल में - और कुछ अन्य) का प्रतिनिधित्व करता है।

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

तो स्ट्रिंग मिलान के दो तरीके हैं: ग्लोब पैटर्न और नियमित अभिव्यक्ति? क्या ग्लोब पेटर्न न केवल फ़ाइल नामों के लिए उपयोग किया जाता है? बैश में, ग्लोब पैटर्न का उपयोग कब करें और नियमित अभिव्यक्ति का उपयोग कब करें? धन्यवाद!
टिम

1
@ समय: ग्लोबिंग बैश के अधिकांश या सभी संस्करणों में उपलब्ध है। रेगेक्स मिलान केवल संस्करण 3 और उच्चतर में उपलब्ध है, लेकिन मैं केवल 3.2 और बाद में इसका उपयोग करने की सलाह दूंगा। Regexes ग्लोबिंग की तुलना में बहुत अधिक बहुमुखी हैं।
अगली सूचना तक रोक दिया गया।



7

अधिक पोर्टेबल समाधान में रुचि रखने वालों के लिए 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, लेकिन पुनर्निर्देशन फिर से सबसे पोर्टेबल है।


egrep के लिए एक बंद ")" भूल गए
ghostdog74

5
के grep -qबजाय का उपयोग करें grep >/dev/null
bfontaine

3

@OP,

क्या ग्लोब पेटर्न न केवल फ़ाइल नामों के लिए उपयोग किया जाता है?

नहीं, "ग्लोब" पैटर्न केवल फ़ाइल नामों के लिए उपयोग नहीं किया जाता है। आप इसे तार के रूप में अच्छी तरह से तुलना करने के लिए उपयोग करते हैं। अपने उदाहरणों में, आप स्ट्रिंग्स पैटर्न देखने के लिए केस / एसैक का उपयोग कर सकते हैं।

 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

बैश में, ग्लोब पैटर्न का उपयोग कब करें और नियमित अभिव्यक्ति का उपयोग कब करें? धन्यवाद!

रेगेक्स "ग्लोब पैटर्न" की तुलना में अधिक बहुमुखी और "सुविधाजनक" है, हालांकि जब तक आप जटिल कार्य नहीं कर रहे हैं कि "ग्लोबिंग / एक्सटेंडेड ग्लोबिंग" आसानी से प्रदान नहीं कर सकते हैं, तो रेगेक्स का उपयोग करने की कोई आवश्यकता नहीं है। Regex को bash <3.2 के संस्करण के लिए समर्थित नहीं है (जैसा कि डेनिस उल्लेख किया गया है), लेकिन आप अभी भी विस्तारित ग्लोबिंग (सेटिंग द्वारा extglob) का उपयोग कर सकते हैं । विस्तारित ग्लोबिंग के लिए, यहां देखें और कुछ सरल उदाहरण यहां दिए गए हैं

ओपी के लिए अपडेट: 2 वर्णों (डॉट्स) के साथ शुरू होने वाली फ़ाइलों को खोजने के लिए उदाहरण। 1 का मतलब है)

उदा आउटपुट

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

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

उपरोक्त में, फ़ाइलों का मिलान किया जाता है क्योंकि उनके नाम में 2 अक्षर होते हैं जिसके बाद "g" होता है। (अर्थात..g )।

ग्लोबिंग के साथ समतुल्य कुछ इस तरह होगा: ( अर्थ के संदर्भ में देखें ?और *)

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

धन्यवाद ghostdog74 3.2 से अधिक संस्करण वाले बैश में, जहाँ कहीं भी उत्तरार्द्ध दिखाई देता है, वहाँ नियमित अभिव्यक्ति का उपयोग ग्लोब पैटर्न को बदलने के लिए किया जा सकता है? या नियमित अभिव्यक्ति का उपयोग केवल कुछ विशेष परिस्थितियों में किया जा सकता है? उदाहरण के लिए, मैंने पाया कि "ls ?? g" काम कर रहा है जबकि "ls ..g" नहीं है।
टिम

यदि आवश्यक हो तो regex का उपयोग करने के लिए आपको कोई रोक नहीं है। यह आप पर निर्भर करता है। नोट, रेगेक्स सिंटैक्स शेल ग्लोबिंग सिंटैक्स से अलग है। इसलिए ls ..gकाम नहीं करता। आप शेल को उस फ़ाइल की तलाश करने के लिए कह रहे हैं जिसका नाम है ..g। रेगुलर एक्सप्रेशन से वाक्य रचना के बारे में सीखने के लिए के रूप में, तुम कोशिश कर सकते perldoc perlretut, perldoc perlrequickहै, या एक कर info sedकमांड लाइन पर।
ghostdog74
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.