चूंकि किसी और ने पूछे गए सवाल का सीधा जवाब नहीं दिया , इसलिए मैं इसे करूंगा।
इसका उत्तर यह है कि POSIX के साथ grep
, इस अनुरोध को सचमुच पूरा करना असंभव है:
grep "<Regex for 'doesn't contain hede'>" input
इसका कारण यह है कि POSIX grep
को केवल बेसिक रेगुलर एक्सप्रेशंस के साथ काम करने की आवश्यकता होती है , जो केवल उस कार्य को पूरा करने के लिए पर्याप्त शक्तिशाली नहीं होते हैं (वे वैकल्पिक भाषाओं और पेरेंटेस की कमी के कारण नियमित भाषाओं को पार्स करने में सक्षम नहीं होते हैं)।
हालांकि, जीएनयू grep
विस्तार को लागू करता है जो इसे अनुमति देता है। विशेष रूप से, \|
बीआरईएस के जीएनयू के क्रियान्वयन में प्रत्यावर्तन ऑपरेटर है, और \(
और \)
कोष्ठकों हैं। यदि आपका नियमित अभिव्यक्ति इंजन वैकल्पिक, नकारात्मक ब्रैकेट भाव, कोष्ठक और क्लेन स्टार का समर्थन करता है, और स्ट्रिंग की शुरुआत और अंत में लंगर डालने में सक्षम है, तो आपको इस दृष्टिकोण की आवश्यकता है। ध्यान दें कि नकारात्मक सेट [^ ... ]
उन लोगों के अलावा बहुत सुविधाजनक हैं, क्योंकि अन्यथा, आपको उन्हें उस फॉर्म की अभिव्यक्ति के साथ बदलने की ज़रूरत है (a|b|c| ... )
जो हर चरित्र को सूचीबद्ध करता है जो सेट में नहीं है, जो बेहद थकाऊ और पीढ़ी से लंबा है, और भी बहुत कुछ पूरा चरित्र सेट यूनिकोड है।
GNU के साथ grep
, उत्तर कुछ इस प्रकार होगा:
grep "^\([^h]\|h\(h\|eh\|edh\)*\([^eh]\|e[^dh]\|ed[^eh]\)\)*\(\|h\(h\|eh\|edh\)*\(\|e\|ed\)\)$" input
( ग्रिल के साथ मिला और हाथ से किए गए कुछ और अनुकूलन)।
आप ऐसे टूल का भी उपयोग कर सकते हैं , जो रेगुलर एक्सप्रेशंस को लागू करता है , जैसे egrep
, बैकस्लैश से छुटकारा पाने के लिए:
egrep "^([^h]|h(h|eh|edh)*([^eh]|e[^dh]|ed[^eh]))*(|h(h|eh|edh)*(|e|ed))$" input
इसकी जांच करने के लिए एक स्क्रिप्ट यहां दी गई है (ध्यान दें कि यह testinput.txt
वर्तमान निर्देशिका में एक फ़ाइल उत्पन्न करता है ):
#!/bin/bash
REGEX="^\([^h]\|h\(h\|eh\|edh\)*\([^eh]\|e[^dh]\|ed[^eh]\)\)*\(\|h\(h\|eh\|edh\)*\(\|e\|ed\)\)$"
# First four lines as in OP's testcase.
cat > testinput.txt <<EOF
hoho
hihi
haha
hede
h
he
ah
head
ahead
ahed
aheda
ahede
hhede
hehede
hedhede
hehehehehehedehehe
hedecidedthat
EOF
diff -s -u <(grep -v hede testinput.txt) <(grep "$REGEX" testinput.txt)
मेरे सिस्टम में यह प्रिंट करता है:
Files /dev/fd/63 and /dev/fd/62 are identical
जैसा सोचा था।
विवरण में रुचि रखने वालों के लिए, नियोजित तकनीक नियमित अभिव्यक्ति को बदलने के लिए है जो शब्द को एक परिमित ऑटोमेटन में बदल देती है, फिर हर स्वीकृति स्थिति को गैर-स्वीकृति और इसके विपरीत में बदलकर ऑटोमेटन को उलट देती है, और फिर परिणामी एफए को वापस परिवर्तित करती है। एक नियमित अभिव्यक्ति।
अंत में, जैसा कि सभी ने नोट किया है, यदि आपका नियमित अभिव्यक्ति इंजन नकारात्मक रूपांतर का समर्थन करता है, जो कार्य को बहुत सरल करता है। उदाहरण के लिए, GNU grep के साथ:
grep -P '^((?!hede).)*$' input
अपडेट: मुझे हाल ही में PHP में लिखी केंडल हॉपकिंस की उत्कृष्ट फॉर्मल थ्योरी लाइब्रेरी मिली है , जो ग्रिल के समान एक कार्यक्षमता प्रदान करती है। इसका उपयोग करते हुए, और खुद के द्वारा लिखा गया एक सरलीकृत, मैं एक नियमित वाक्यांश के ऑनलाइन जनरेटर को लिखने में सक्षम हूं, जो एक इनपुट वाक्यांश (वर्तमान में समर्थित केवल अल्फ़ान्यूमेरिक और अंतरिक्ष वर्ण) दिए गए हैं: http://www.formauri.es/personal/ pgimeno / विविध / गैर मैच regex /
इसके लिए hede
आउटपुट:
^([^h]|h(h|e(h|dh))*([^eh]|e([^dh]|d[^eh])))*(h(h|e(h|dh))*(ed?)?)?$
जो ऊपर के बराबर है।
([^h]*(h([^e]|$)|he([^d]|$)|hed([^e]|$)))*
:? विचार सरल है। जब तक आप अवांछित स्ट्रिंग की शुरुआत नहीं देखते तब तक मिलान करते रहें, फिर केवल एन -1 मामलों में मिलान करें जहां स्ट्रिंग अधूरा है (जहां एन स्ट्रिंग की लंबाई है)। ये एन -1 मामले "गैर-ई के बाद एच", "उसके बाद गैर-डी", और "गैर-ई द्वारा पीछा किए जाने वाले" हैं। यदि आप इन एन -1 मामलों को पारित करने में कामयाब रहे, तो आप अवांछित स्ट्रिंग से सफलतापूर्वक मेल नहीं खाते, ताकि आप[^h]*
फिर से तलाश शुरू कर सकें