2012-03-20 14 views
15

मैं (डुप्लिकेट से बचने के लिए) फिर उस शब्द जोड़ने से पहले एक सूची में एक शब्द की उपस्थिति पर मैच के लिए कोशिश कर रहा हूँ। मैं bash 4.2.24 का उपयोग कर रहा है और नीचे कोशिश कर रहा हूँ:बैश समर्थन शब्द सीमा नियमित अभिव्यक्ति करता है?

[[ $foo =~ \bmyword\b ]] 

भी

[[ $foo =~ \<myword\> ]] 

हालांकि, न तो काम करने के लिए लग रहे हैं। उनका उल्लेख बैश डॉक्स उदाहरण में किया गया है: http://tldp.org/LDP/Bash-Beginners-Guide/html/sect_04_01.html

मुझे लगता है मैं कुछ गलत कर रहा हूं, लेकिन मुझे यकीन है कि क्या नहीं कर रहा हूँ। किसी भी मार्गदर्शन की सराहना की ...

+3

एक तरफ के रूप में: बैश के '= ~' ऑपरेटर का व्यवहार _platform-dependent_ है, क्योंकि मेजबान प्लेटफॉर्म के रेगेक्स पुस्तकालयों का उपयोग किया जाता है। इस प्रकार, उदाहरण के लिए, स्वीकृत उत्तर में कार्यवाही के साथ, '\ b' और' \ <'/'\> 'ओएसएक्स जैसे बीएसडी-जैसी प्रणालियों पर काम नहीं करेगा। इसके विपरीत, ओएसएक्स '[[: \ <:]]' और '[[: \>:]]' का समर्थन करता है, जो लिनक्स पर काम नहीं करेगा। – mklement0

उत्तर

20

हाँ, सभी सूचीबद्ध regex एक्सटेंशन का समर्थन कर रहे हैं, लेकिन आप बेहतर भाग्य उपयोग करने से पहले एक चर में पैटर्न डाल होगा। इस प्रयास करें: चारों ओर मैं this question पाया

re=\\bmyword\\b 
[[ $foo =~ $re ]] 

खुदाई, जिसका जवाब की व्याख्या करने क्यों व्यवहार बदल जाता है जब regex अपने उदाहरण के रूप में इनलाइन लिखा है लगता है। आप शायद अपने परीक्षण के पुनर्लेखन के लिए इतनी के रूप में अपने regexes के लिए एक अस्थायी चर का उपयोग करने के लिए है, या 3.1 संगतता मोड का उपयोग करेंगे:

shopt -s compat31 
+0

शानदार, धन्यवाद। यह अच्छी तरह से काम करता है। क्या आपको बस बैश पसंद नहीं है;) – starfry

+4

+1। वैकल्पिक रूप से, आप कमांड प्रतिस्थापन का उपयोग कर सकते हैं: '[[$ foo = ~ $ (echo' \ ')]] '। यह अभी भी कष्टप्रद वर्बोज़ है, लेकिन कम से कम एक भयानक चर की आवश्यकता नहीं है। – ruakh

+0

bash @Eduardo Ivanec का आपका संस्करण क्या है? क्या यह उसमें काम करता है? कामकाज के लिए – Prospero

18

tl; डॉ

  • सुरक्षा के लिए, =~ साथ एक regex शाब्दिक प्रयोग नहीं करते।
    इसके बजाय, उपयोग:

  • चाहे \b और \</\> काम सभी पर मेजबान मंच पर निर्भर करता है, नहीं मार :

    • वे काम करते लिनक्स,
    • लेकिन पर बीएसडी आधारित प्लेटफॉर्म पर इस तरह के रूप MacOS नहीं।

आप और अधिक जानना चाहते हैं, पर पढ़ें।


bash 3.2+ पर है (बशर्ते compat31shopt विकल्प सेट किया गया है), =~ ऑपरेटर की सही संकार्य होना चाहिए गैर उद्धृत क्रम में एक regex (रूप में पहचाना जाने अगर आप बोली दायां ऑपरेंड, =~ इसके बजाय नियमित स्ट्रिंग तुलना निष्पादित करता है)।

अधिक सही, कम से कम विशेष regex अक्षर और दृश्यों होना चाहिए गैर उद्धृत, तो यह उन सबस्ट्रिंग कि सचमुच लिया जाना चाहिए उद्धृत करने के लिए ठीक है और उपयोगी है; उदाहरण के लिए, [[ ' ab' =~ ^' ab' ]] मैचों, क्योंकि ^unquoted है और इस प्रकार सही ढंग से स्टार्ट-ऑफ-स्ट्रिंग एंकर के रूप में पहचाना जाता है।

हालांकि, वहाँ इस तरह के \< और \s रूप \ -prefixed निर्माणों हों उनके ((कम से कम) bash 4.x जहां कुछ regex शाब्दिक ठीक प्रकार से पार्स नहीं कर रहे हैं, अर्थात् में एक बग प्रतीत होता है यदि आपको लगता है कि यह कोई बग नहीं है, तो मुझे) बताएं; bash 4.2.46 पर Linux के रूप में व्यवहार:

# BUG 
[[ ' word ' =~ \<word\> ]] && echo MATCHES  # !! DOES NOT MATCH 
[[ ' word ' =~ \\<word\\> ]] && echo MATCHES # !! BREAKS 
[[ ' word ' =~ \\\<word\\\> ]] && echo MATCHES # !! DOES NOT MATCH 

    # WORKAROUNDS 
re='\<word\>'; [[ ' word ' =~ $re ]] && echo MATCHES # OK - intermediate variable 
[[ ' word ' =~ $(printf %s '\<word\>') ]] && echo MATCHES # OK - command subst. 

क्रॉस-प्लेटफॉर्म समर्थन:

=~ दुर्लभ मामला एक की (? केवल मामले)bash विशेषता है कि निर्मित है प्लेटफार्म-निर्भर: यह उस प्लेटफ़ॉर्म के रेगेक्स पुस्तकालयों का उपयोग करता है जो इसके चलते चल रहा है, जिसके परिणामस्वरूप विभिन्न प्लेटफ़ॉर्म पर विभिन्न रेगेक्स स्वाद एस

उदाहरण के लिए, FreeBSD/OSX\</\> और \b पर समर्थित नहीं हैं, लेकिन [[:<:]] और [[:>:]] हैं। लिनक्स पर यह दूसरी तरफ है।

इस प्रकार, यह गैर-तुच्छ है और पोर्टेबल कोड लिखने के लिए अतिरिक्त देखभाल की आवश्यकता है जो =~ ऑपरेटर का उपयोग करता है।

-1
अपने प्रश्न का

स्पर्शरेखा, लेकिन आप अपनी स्क्रिप्ट में egrep उपयोग कर सकते हैं:

if [ `echo $foo | egrep -c "\b${myword}\b"` -gt 0 ]; then 

मैं के साथ घिसटते हुए के बाद इस का उपयोग कर समाप्त हो गया बैश के =~

रूप mklement0 के astutely बताते हैं, हम सिर्फ भरोसा कर सकता है egrep के जाने की स्थिति और लिखने पर:

if egrep -q "\b${myword}\b" <<<$foo; then 
+2

आप बंद करने से पहले एक स्थान खो रहे हैं ']'; आप इसे सरल बना सकते हैं: 'अगर echo $ foo | egrep -q "\ b $ {myword} \ b"; फिर 'या यहां तक ​​कि' अगर egrep -q "\ b $ {myword} \ b" <<< $ foo; then'।एक तरफ नोट (हाथ में मामले में कोई समस्या नहीं): आप '= ~' का उपयोग न करके subexpressions ('$ {BASH_REMATCH [@]}' के माध्यम से) को कैप्चर करने की क्षमता खो देते हैं। – mklement0

+1

धन्यवाद @ mklement0, मैंने अंतरिक्ष अपडेट किया और आपकी टिप्पणी का ध्यान दिया। –

+1

@ mklement0 टिप्पणी एक नहीं है नोट क्या आप दिखा रहे हैं मूर्खता से जटिल है और का एक बुरा समझ सुझाव है अगर वाक्य रचना, और तथ्य यह है कि '[...]' 'परीक्षण के रूप में एक ही है की विशेष रूप से .. ।, यानी सिर्फ एक और नियमित आदेश। –

0

यह मैं

के लिए काम किया
bar='\<myword\>' 
[[ $foo =~ $bar ]] 
+0

हां, लेकिन यह प्रभावी रूप से स्वीकार किए गए उत्तर के समान ही है। लिनक्स, दोनों 'बार = '\ '' और 'बार = 'पर \ bmyword \ b'' काम (या गैर उद्धृत, स्वीकार किए जाते हैं जवाब है,' बार = \\ bmyword \\ b' के रूप में)। – mklement0

3

स्वीकार्य उत्तर बैश के [[ ... ]] अभिव्यक्तियों में नियमित अभिव्यक्तियों की वाक्यविन्यास विषमताओं से निपटने के लिए सहायक चर का उपयोग करने पर केंद्रित है। बहुत अच्छी जानकारी।

हालांकि, वास्तविक जवाब है:

\b\< और \> बैश संस्करण 4.3.42 (1) -release (x86_64-सेब के darwin15 साथ पर ओएस एक्स 10.11.5 (एल कैप्टन) काम नहीं करते। 0.0)।

इसके बजाय, [[:<:]] और [[:>:]] का उपयोग करें।

+1

@ mklement0 से मूल प्रश्न पर एक टिप्पणी है जो यह भी कहती है। – starfry

0

नहीं वास्तव में "\ ख", लेकिन मुझे और अधिक पठनीय (और पोर्टेबल) अन्य सुझावों से के लिए:

[[ $foo =~ (^|)myword($|) ]] 
0

आप ग्रेप, जो इस तरह की पार्टी के regexp की तुलना में अधिक पोर्टेबल है का उपयोग कर सकते हैं:

if echo $foo | grep -q '\<myword\>'; then 
    echo "MATCH"; 
else 
    echo "NO MATCH"; 
fi 
0

मैंने पुराने सिस्टम पर शब्द सीमाओं से मेल खाने के लिए निम्नलिखित का उपयोग किया है। कुंजी $foo को [^[:alpha:]] से रिक्त स्थान के साथ लपेटना है क्योंकि सूची की शुरुआत या अंत में शब्दों से मेल नहीं खाएगा।

[[ " $foo " =~ [^[:alpha:]]myword[^[:alpha:]] ]] 

चरित्र वर्ग के रूप में myword की उम्मीद सामग्री के आधार पर की जरूरत है ठीक करना है, अन्यथा यह अच्छा समाधान नहीं हो सकता।

संबंधित मुद्दे