मैं एक फ़ाइल में एक बहुस्तरीय पैटर्न कैसे खोज सकता हूं?


128

मुझे उन सभी फाइलों को खोजने की जरूरत थी जिनमें एक विशिष्ट स्ट्रिंग पैटर्न था। पहला समाधान जो मन में आता उपयोग कर रहा है खोजने के साथ पहुंचाया xargs ग्रेप :

find . -iname '*.py' | xargs grep -e 'YOUR_PATTERN'

लेकिन अगर मुझे ऐसे पैटर्न खोजने की ज़रूरत है जो एक से अधिक लाइन पर फैलते हैं, तो मैं अटक जाता हूं क्योंकि वेनिला जीआरपी मल्टीलाइन पैटर्न नहीं पा सकता है।



2
यह एक पुराना है, इसलिए मैं कहूंगा कि यह डुप्लिकेट नहीं है :)
rogerdpack

@rogerdpack जब डुप्लिकेट के रूप में प्रश्नों को चिह्नित करते हैं, तो एक प्रश्न की आयु एक तृतीयक चिंता है, उत्तर की मात्रा और गुणवत्ता के बाद और प्रश्न की गुणवत्ता।
ट्रिपल

जवाबों:


98

इसलिए मैंने pcregrep की खोज की जो पर्ल कम्पेटिबल रेगुलर एक्सप्रेशंस GREP के लिए है

उदाहरण के लिए, आप फ़ाइलों को जहां 'खोजने की जरूरत है नाम_ ' चर immediatelly 'द्वारा पीछा किया जाता _description ' चर:

find . -iname '*.py' | xargs pcregrep -M '_name.*\n.*_description'

युक्ति: आपको अपने पैटर्न में लाइन ब्रेक चरित्र को शामिल करने की आवश्यकता है। आपके प्लेटफॉर्म के आधार पर, यह '\ n', \ r ',' \ r \ n ', हो सकता है ...


7
जैसा कि नीचे हलका द्वारा उल्लेख किया गया है, "यदि आप अपनी नियमित अभिव्यक्ति में जोड़ते हैं तो आप नई वाइल्डलाइन से मेल खाने के लिए डॉट वाइल्डकार्ड को भी राजी कर सकते हैं"। फिर जोड़कर perl regex के साथ grep का उपयोग करें। खोजो। -exec grep -nHP '(? s) का चयन करें। {1,60} FROM। {1,20} table_name' '{}' ';
जिम

8
pcregrepमैक पर उपलब्ध हैbrew install pcre
जारेड बेक

1
इससे भी बेहतर: -Hप्रत्येक मैच से पहले फाइलनाम को प्रिंट करने वाले का भी उपयोग करें pcregrep -HM:।
सिरो सेंटिल्ली 郝海东 i iro i 法轮功 '21

97

तुम जाग क्यों नहीं जाते :

awk '/Start pattern/,/End pattern/' filename

2
यह समझना बहुत आसान है और उपयोग करता है awkजो अधिकांश * निक्स सिस्टम के साथ आता है।
अली करबासि

24
अच्छा! क्या इस मैच को गैर-लालची बनाने का कोई तरीका है?
१०:१६

3
मैच होने पर आप केवल नाम कैसे छापेंगे?
14

2
आप के साथ मैचों की लाइन संख्या दिखा सकते हैं awk '/Start pattern/,/End pattern/ {printf NR " "; print}' filename। आप लाइन संख्या को निश्चित चौड़ाई देकर इसे पूर्ववर्ती बना सकते हैं awk '/Start pattern/,/End pattern/ {printf "%-4s ", NR; print}' filename:।
रॉबर्ट

यह एकल फ़ाइल पर अच्छी तरह से काम करने लगता है, हालांकि, क्या होगा अगर मैं कई फ़ाइलों के भीतर खोज करना चाहता हूं?
जिनस्ट्रॉन्ग

84

यहाँ जीएनयूgrep का उपयोग करके उदाहरण दिया गया है :

grep -Pzo '_name.*\n.*_description'

-z/ --null-dataइनपुट और आउटपुट डेटा को लाइनों के अनुक्रम के रूप में समझें।

यहां भी देखें


1
मुझे लगता है कि केवल एक ही नई लाइन के चरित्र के लिए, मुझे लगता है।
क्लाउड

1
मैं झंडे का उपयोग किए बिना, बहु-खोज के लिए grep का उपयोग करने में सक्षम नहीं था, -zइसलिए यह एकल पंक्ति पर खोज को विभाजित नहीं करता है, और -oकेवल मिलान वाले भाग को प्रिंट करने के लिए।
bbaja42

मैंने पाया कि -इसके कारण कुछ भी प्रिंट नहीं किया गया, लेकिन -l ने फाइलों की एक सूची प्राप्त करने के लिए काम किया (मेरी कमांड थी grep -rzl pattern *, -रो ने काम नहीं किया)
बेनुबर्ड

5
मैं गैर-ASCII फाइलों के लिए '' -Pzo '' के बजाय '' grep -Pazo '' की सलाह देता हूं । यह बेहतर है क्योंकि गैर-ASCII फाइलों पर -z स्विच grep के "बाइनरी डेटा" व्यवहार को ट्रिगर कर सकता है जो रिटर्न मान को बदलता है। स्विच '' -a | --text '' जो रोकता है।
rloth

मैक पर काम नहीं करता के साथ स्थापित git के साथbrew reinstall --with-pcre git
क्वांलोंग

21

grep -Pभी libpcre का उपयोग करता है, लेकिन बहुत अधिक व्यापक रूप से स्थापित है। titleएक HTML दस्तावेज़ का एक पूरा खंड खोजने के लिए , भले ही यह कई पंक्तियों में फैला हो, आप इसका उपयोग कर सकते हैं:

grep -P '(?s)<title>.*</title>' example.html

चूंकि पीसीआरई परियोजना पर्ल मानक पर लागू होती है, इसलिए संदर्भ के लिए पर्ल दस्तावेज का उपयोग करें:


हम्म ने अभी यह कोशिश की और काम नहीं किया ... gist.github.com/rdp/0286d91624930bd11d0169d6a6337c33
rogerdpack

मुझे नहीं पता था कि grep के पास यह विकल्प था। संभवतः इस वजह से: यह अत्यधिक प्रायोगिक है और grep -P अनिमित सुविधाओं की चेतावनी दे सकता है। ; यह CentOS 7 के तहत है। फेडोरा 29 के तहत: यह प्रायोगिक और grep -पी है जो अनिमित सुविधाओं के बारे में चेतावनी दे सकता है । निश्चित रूप से बीएसडी grep में यह बिल्कुल नहीं है। अच्छा होगा अगर यह इतना प्रायोगिक नहीं था, लेकिन इसे याद दिलाना अच्छा है - हालांकि मुझे इसके उपयोग की संभावना कम है।
प्रिएफ्टन

17

यहाँ एक और अधिक उपयोगी उदाहरण है:

pcregrep -Mi "<title>(.*\n){0,5}</title>" afile.html

यह एक html फ़ाइल में शीर्षक टैग खोजता है, भले ही वह 5 पंक्तियों तक फैला हो।

यहाँ असीमित लाइनों का एक उदाहरण है:

pcregrep -Mi "(?s)<title>.*</title>" example.html 

4
इसके लिए धन्यवाद। मुझे यह एहसास नहीं था कि वाइल्डकार्ड न्यूलाइन कैरेक्टर से मेल नहीं खाएगा।
मैट

7
@matt: यदि आप (?s)अपनी नियमित अभिव्यक्ति में जोड़ते हैं तो आप नई वाइल्डलाइन से मेल खाने के लिए डॉट वाइल्डकार्ड भी बना सकते हैं , जैसे:"(?s)<html>.*</html>"
lubomir.brindza

@ निश्चित रूप से आप यह देख सकते हैं कि $(पैटर्न के अंत में) यह इंगित करने के लिए कि यह पंक्ति का अंत है - हालांकि यह वही नहीं है जो आपको कई लाइन पैटर्न खोजने में मदद करता है। यह भी देखें glob(7)। आपको यह ब्याज की वेबसाइट भी मिल सकती है: regular-expressions.info
Pryftan


4

आप grep वैकल्पिक sift का उपयोग कर सकते हैं यहाँ का (अस्वीकरण: मैं लेखक हूँ)।

यह बहु-मिलान और बॉक्स से बाहर विशिष्ट फ़ाइल प्रकारों की खोज को सीमित करने का समर्थन करता है:

sift -m --files '* .py' 'your_PATTERN'

(सभी खोज करें। निर्दिष्ट मल्टीलाइन रेगेक्स पैटर्न के लिए .py फाइलें)

यह सभी प्रमुख ऑपरेटिंग सिस्टम के लिए उपलब्ध है। नमूने पृष्ठ पर एक नज़र डालें कि यह कैसे एक्सएमएल फ़ाइल से बहुस्तरीय मान निकालने के लिए इस्तेमाल किया जा सकता है।


3

यह उत्तर उपयोगी हो सकता है:

मल्टी-लाइन खोज के लिए रेगेक्स (grep) की आवश्यकता है

पुनरावर्ती खोजने के लिए आप झंडे -R (पुनरावर्ती) और --include (GLOB पैटर्न) का उपयोग कर सकते हैं। देख:

Grep --exclude का उपयोग करें - कुछ फ़ाइलों के माध्यम से grep न करने के लिए सिंटैक्स शामिल करें


@ Editingiamond ƦeezeƦ ध्यान दें कि LQP ( stackoverflow.com/review/low-quality-posts/19341146 ) में एक पोस्ट को संपादित करने से समीक्षा अमान्य हो जाती है, इसलिए यदि आप सुनिश्चित हैं कि पोस्ट को बनाए रखने की आवश्यकता है तो बस संपादित करें।
फेडोरक्वी 'SO

2

@ मार्सिन: awk उदाहरण गैर-लालची:

awk '{if ($0 ~ /Start pattern/) {triggered=1;}if (triggered) {print; if ($0 ~ /End pattern/) { exit;}}}' filename


1

ex/ viसंपादक और ग्लोबस्टार विकल्प (के समान सिंटैक्स ) awkऔर का उपयोग करना sed:

ex +"/string1/,/string3/p" -R -scq! file.txt

aaaआपका शुरुआती बिंदु कहां है, औरbbb आपका अंतिम पाठ है।

पुनरावर्ती खोज करने के लिए, प्रयास करें:

ex +"/aaa/,/bbb/p" -scq! **/*.py

नोट: **सिंटैक्स को सक्षम करने के लिए , चलाएं shopt -s globstar(बैश 4 या zsh)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.