इस प्रश्न की व्याख्या करने के दो तरीके हैं; मैं दोनों मामलों को संबोधित करूंगा। आप लाइनें प्रदर्शित करना चाह सकते हैं:
- इसमें चार अंकों का एक क्रम होता है जो कि अंकों के किसी भी लंबे अनुक्रम का हिस्सा नहीं है, या
- इसमें चार अंकों का अनुक्रम होता है, लेकिन अंकों का कोई अनुक्रम नहीं होता (अलग से भी नहीं)।
उदाहरण के लिए, (1) प्रदर्शित होगा 1234a56789
, लेकिन (2) नहीं होगा।
यदि आप उन सभी रेखाओं को प्रदर्शित करना चाहते हैं जिनमें चार अंकों का अनुक्रम होता है, जो कि अंकों के किसी भी लंबे अनुक्रम का हिस्सा नहीं है, तो एक तरीका:
grep -P '(?<!\d)\d{4}(?!\d)' file
यह पर्ल रेगुलर एक्सप्रेशंस का उपयोग करता है , जो कि Ubuntu grep
( GNU grep ) के माध्यम से सपोर्ट करता है -P
। यह पाठ की तरह मेल नहीं खाएगा 12345
, और न ही इसका मिलान होगा 1234
या 2345
इसका हिस्सा होगा। लेकिन यह से मेल खाएगी 1234
में 1234a56789
।
पर्ल नियमित अभिव्यक्तियों में:
\d
किसी भी अंक का मतलब है (यह कहने का छोटा तरीका है [0-9]
या [[:digit:]]
)।
x{4}
x
4 बार मेल खाता है। ( {
}
वाक्यविन्यास पर्ल नियमित अभिव्यक्तियों के लिए विशिष्ट नहीं है; यह विस्तारित नियमित अभिव्यक्तियों grep -E
में भी है।) तो \d{4}
जैसा है वैसा ही है \d\d\d\d
।
(?<!\d)
एक शून्य-चौड़ाई नकारात्मक रूप-दर्शन के पीछे है। इसका मतलब है "जब तक पहले नहीं \d
।"
(?!\d)
शून्य-चौड़ाई वाला नकारात्मक रूप-आगे मुखर है। इसका मतलब है "जब तक पीछा नहीं किया जाता है \d
।"
(?<!\d)
और (?!\d)
चार अंकों के अनुक्रम के बाहर पाठ से मेल नहीं खाते; इसके बजाय, वे (जब एक साथ उपयोग किए जाते हैं) चार अंकों के अनुक्रम को अपने आप से मिलान होने से रोकते हैं यदि यह अंकों के लंबे अनुक्रम का हिस्सा है।
सिर्फ लुक-पीछे या सिर्फ लुक-फॉरवर्ड का उपयोग करना अपर्याप्त है, क्योंकि सबसे दाहिने या बाएं चार अंकों के बाद भी मिलान किया जाएगा।
लुक-बैक और लुक-फॉरवर्ड अभिकथन का उपयोग करने का एक फायदा यह है कि आपका पैटर्न केवल चार अंकों के अनुक्रम से मेल खाता है, न कि आसपास के पाठ से। रंग हाइलाइटिंग ( --color
विकल्प के साथ ) का उपयोग करते समय यह सहायक होता है ।
ek@Io:~$ grep -P '(?<!\d)\d{4}(?!\d)' <<< 12345abc789d0123e4
12345abc789d0123e4
उबंटू में डिफ़ॉल्ट रूप से, प्रत्येक उपयोगकर्ता alias grep='grep --color=auto'
अपनी ~.bashrc
फ़ाइल में है । तो तुम जब तुम एक साधारण के साथ शुरू कमांड चलाएँ स्वचालित रूप से प्रकाश डाला रंग प्राप्त grep
(यह तब होता है जब उपनाम का विस्तार कर रहे हैं) और मानक आउटपुट है एक टर्मिनल (यह क्या है के लिए चेक)। माचिस को आमतौर पर लाल रंग की छाया ( सिंदूर के करीब ) में हाइलाइट किया जाता है , लेकिन मैंने इसे इटैलिकाइज़्ड बोल्ड में दिखाया है। यहाँ एक स्क्रीनशॉट है:--color=auto
और आप grep
केवल प्रिंट से मेल खाते हुए टेक्स्ट बना सकते हैं , न कि पूरी लाइन के साथ -o
:
ek@Io:~$ grep -oP '(?<!\d)\d{4}(?!\d)' <<< 12345abc789d0123e4
0123
अल्टरनेटिव वे, विदाउट लुक-बिहाइंड और लुक-अहेड असेसरीज
हालाँकि, यदि आप:
- एक ऐसी कमांड की आवश्यकता है जो उन प्रणालियों पर भी चलेगी जहां
grep
समर्थन नहीं है -P
या अन्यथा पर्ल नियमित अभिव्यक्ति का उपयोग नहीं करना चाहते हैं, और
- विशेष रूप से चार अंकों से मेल खाने की ज़रूरत नहीं है - जो आमतौर पर मामला है यदि आपका लक्ष्य बस मैच युक्त लाइनें प्रदर्शित करना है, और
- एक समाधान के साथ ठीक हैं जो थोड़ा कम सुरुचिपूर्ण है
... तो आप इसके बजाय एक विस्तारित नियमित अभिव्यक्ति के साथ इसे प्राप्त कर सकते हैं :
grep -E '(^|[^0-9])[0-9]{4}($|[^0-9])' file
यह चार अंकों और गैर-अंकीय चरित्र से मेल खाता है - या रेखा के आरंभ या अंत में - उनके आसपास। विशेष रूप से:
[0-9]
किसी भी अंक से मेल खाता है (जैसे [[:digit:]]
, या \d
पर्ल नियमित अभिव्यक्तियों में) और {4}
इसका अर्थ है "चार बार।" तो [0-9]{4}
चार अंकों के क्रम से मेल खाता है।
[^0-9]
मैचों के 0
माध्यम से वर्णों की श्रेणी में नहीं है 9
। यह [^[:digit:]]
(या \D
, पर्ल नियमित अभिव्यक्तियों में) के बराबर है ।
^
, जब यह [
]
कोष्ठक में प्रकट नहीं होता है , एक पंक्ति की शुरुआत से मेल खाता है। इसी तरह, $
एक पंक्ति के अंत से मेल खाता है।
|
साधन या कोष्ठक समूहन के लिए हैं (जैसे बीजगणित में)। तो (^|[^0-9])
लाइन की शुरुआत या एक गैर-अंक चरित्र से ($|[^0-9])
मेल खाता है , जबकि रेखा के अंत या एक गैर-अंक चरित्र से मेल खाता है।
तो मैच केवल चार अंकों वाले अनुक्रम में होते हैं ( [0-9]{4}
) जो एक साथ होता है:
- लाइन की शुरुआत में या एक गैर-अंक (
(^|[^0-9])
), और से पहले
- पंक्ति के अंत में या एक गैर-अंक (
($|[^0-9])
) के बाद।
यदि, दूसरी ओर, आप उन सभी पंक्तियों को प्रदर्शित करना चाहते हैं जिनमें चार अंकों का अनुक्रम होता है, लेकिन चार अंकों से अधिक का कोई अनुक्रम नहीं होता है (यहां तक कि एक और जो केवल चार अंकों के दूसरे अनुक्रम से अलग होता है), तो वैचारिक रूप से आपके लक्ष्य उन पंक्तियों को खोजना है जो एक पैटर्न से मेल खाती हैं, लेकिन दूसरी नहीं।
इसलिए, भले ही आप यह जानते हों कि इसे एकल पैटर्न के साथ कैसे किया जाता है, मैं मैट के दूसरे सुझाव की तरह कुछ का उपयोग करने का सुझाव दूंगा , grep
दो पैटर्न के लिए अलग-अलग।
ऐसा करते समय आपको पर्ल रेगुलर एक्सप्रेशंस के किसी भी उन्नत फीचर्स से दृढ़ता से लाभ नहीं होता है, इसलिए हो सकता है कि आप उनका उपयोग न करना पसंद करें। लेकिन उपरोक्त शैली को ध्यान में रखते हुए, यहाँ मैट समाधान का उपयोग छोटा \d
(और ब्रेसिज़) के स्थान पर किया गया है [0-9]
:
grep -P '\d{4}' file | grep -Pv '\d{5}'
चूंकि यह उपयोग करता है [0-9]
, मैट का तरीका अधिक पोर्टेबल है - यह उन प्रणालियों पर काम करेगा जहां grep
पर्ल नियमित अभिव्यक्ति का समर्थन नहीं करता है। यदि आप इसके बजाय [0-9]
(या [[:digit:]]
) का उपयोग करते हैं \d
, लेकिन उपयोग करना जारी रखते हैं {
}
, तो आपको मैट के तरीके की पोर्टेबिलिटी थोड़ी अधिक संक्षिप्त रूप से मिलती है:
grep -E '[0-9]{4}' file | grep -Ev '[0-9]{5}'
वैकल्पिक तरीका, एक एकल पैटर्न के साथ
यदि आप वास्तव में एक grep
आदेश पसंद करते हैं कि
- एक नियमित अभिव्यक्ति का उपयोग करता है (दो
grep
एस पाइप से अलग नहीं किया जाता है , ऊपर के रूप में)
- उन रेखाओं को प्रदर्शित करने के लिए जिनमें चार अंकों का कम से कम एक अनुक्रम होता है,
- लेकिन पांच (या अधिक) अंकों का कोई अनुक्रम नहीं,
- और आपको पूरी रेखा से मेल खाने में कोई आपत्ति नहीं है, न कि केवल अंक (आप शायद यह बुरा नहीं मानते)
... तो आप उपयोग कर सकते हैं:
grep -Px '(\d{0,4}\D)*\d{4}(\D\d{0,4})*' file
-x
झंडा बनाता है grep
केवल लाइनों को प्रदर्शित जहां पूरे लाइन मैचों (बजाय किसी भी लाइन युक्त एक मैच)।
मैंने एक पर्ल रेगुलर एक्सप्रेशन का उपयोग किया है क्योंकि मुझे लगता है कि इस मामले में संक्षिप्तता \d
और \D
स्पष्टता बढ़ जाती है। लेकिन अगर आप जहां सिस्टम के लिए कुछ पोर्टेबल की जरूरत grep
का समर्थन नहीं करता -P
है, तो आप उन लोगों के साथ की जगह ले सकता [0-9]
है और [^0-9]
(या के साथ [[:digit:]]
और [^[:digit]]
):
grep -Ex '([0-9]{0,4}[^0-9])*[0-9]{4}([^0-9][0-9]{0,4})*' file
इन नियमित अभिव्यक्तियों के काम करने का तरीका है:
बीच में, \d{4}
या [0-9]{4}
चार अंकों के एक क्रम से मेल खाता है। हमारे पास इनमें से एक से अधिक हो सकते हैं, लेकिन हमें कम से कम एक होना चाहिए।
बाईं ओर, (\d{0,4}\D)*
या ([0-9]{0,4}[^0-9])*
शून्य या अधिक से मेल खाता है ( *
) गैर-अंक के बाद चार अंकों से अधिक नहीं के उदाहरण। शून्य अंक (यानी, कुछ भी नहीं) "चार अंकों से अधिक नहीं" के लिए एक संभावना है। यह (a) खाली स्ट्रिंग या (b) किसी भी स्ट्रिंग को गैर-अंक में समाप्त करता है और जिसमें चार अंकों से अधिक का कोई अनुक्रम नहीं होता है।
चूँकि तुरंत केंद्रीय \d{4}
(या [0-9]{4}
) के बाईं ओर का पाठ रिक्त होना चाहिए या एक गैर-अंक के साथ समाप्त होना चाहिए, यह केंद्रीय \d{4}
को चार अंकों के मिलान से रोकता है जिनके पास बाईं ओर एक और (पांचवां) अंक होता है।
दाईं ओर, (\D\d{0,4})*
या ([^0-9][0-9]{0,4})*
शून्य या अधिक ( *
) एक गैर-अंक के उदाहरणों का अनुसरण करते हैं, जिसके बाद चार अंकों से अधिक नहीं (जो पहले की तरह, चार, तीन, दो, एक, या यहां तक कि कोई भी नहीं हो सकता है)। यह (a) खाली स्ट्रिंग या (b) किसी भी स्ट्रिंग की शुरुआत गैर-अंक में करता है और जिसमें चार अंकों से अधिक का कोई अनुक्रम नहीं होता है।
चूँकि तुरंत केंद्रीय \d{4}
(या [0-9]{4}
) के दाईं ओर पाठ खाली होना चाहिए या एक गैर-अंक के साथ शुरू होना चाहिए, यह केंद्रीय \d{4}
को चार अंकों के मिलान से रोकता है जिनके पास उनके दाईं ओर एक और (पांचवां) अंक होता है।
यह सुनिश्चित करता है कि चार-अंकीय अनुक्रम कहीं मौजूद है, और यह कि पाँच या अधिक अंकों का कोई भी क्रम कहीं भी मौजूद नहीं है।
इसे इस तरह करना बुरा या गलत नहीं है। लेकिन शायद इस विकल्प पर विचार करने का सबसे महत्वपूर्ण कारण यह है कि यह उपर्युक्त और मैट के उत्तर के रूप में इसके बजाय (या समान) के उपयोग के लाभ को स्पष्ट करता है ।grep -P '\d{4}' file | grep -Pv '\d{5}'
इस तरह से, यह स्पष्ट है कि आपका लक्ष्य उन पंक्तियों का चयन करना है जिनमें एक चीज होती है, लेकिन दूसरी नहीं। इसके अलावा वाक्य रचना सरल है (इसलिए यह कई पाठकों / अनुरक्षकों द्वारा अधिक तेज़ी से समझा जा सकता है)।
1234a12345
प्रदर्शित होना चाहिए या नहीं?