2010-05-03 3 views
6

मैंने इसे थोड़ा सा खोजा है, लेकिन मुझे गलत शर्तों का उपयोग करना होगा - क्या रूबी के पास स्ट्रिंग/रेगेक्स के लिए grep का तरीका है और आसपास की 5 लाइनें (ऊपर और नीचे) भी लौटाती है? मुझे पता है कि मैं सिर्फ "grep -C 5 ..." पर कॉल कर सकता हूं या यहां तक ​​कि अपनी खुद की विधि भी लिख सकता हूं, लेकिन ऐसा लगता है कि कुछ रूबी होगी और मैं सिर्फ सही खोज शब्दों का उपयोग नहीं कर रहा हूं।मैच के चारों ओर लाइनों के संदर्भ प्राप्त करने के लिए "grep-c 5" के बराबर रूबी?

उत्तर

6

आप इसे नियमित अभिव्यक्ति के साथ कर सकते हैं। यहाँ स्ट्रिंग हम खोज करना चाहते है:

s = %{The first line 
The second line 
The third line 
The fourth line 
The fifth line 
The sixth line 
The seventh line 
The eight line 
The ninth line 
The tenth line 
} 

EOL मेरे लिए "\ n" है, लेकिन आप के लिए यह हो सकता है "\ r \ n"। सिर्फ एक बार

EOL = '\n' 

नियमित अभिव्यक्ति को आसान बनाने के लिए, हम "संदर्भ" के लिए पैटर्न को परिभाषित करेंगे:: मैं एक निरंतर में यह रह सकते हैं

CONTEXT_LINES = 2 
CONTEXT = "((?:.*#{EOL}){#{CONTEXT_LINES}})" 

और हम किसी भी लाइन के लिए खोज करेंगे शब्द "पांचवां" है। ध्यान दें कि यह नियमित अभिव्यक्ति, पूरे लाइन हड़पने चाहिए अंत लाइन सहित यह काम करने के लिए:

regexp = /.*fifth.*#{EOL}/ 

अंत में, खोज करते हैं और दिखाने के परिणाम:

s =~ /^#{CONTEXT}(#{regexp})#{CONTEXT}/ 
before, match, after = $1, $2, $3 
p before # => "The third line\nThe fourth line\n" 
p match  # => "The fifth line\n" 
p after  # => "The sixth line\nThe seventh line\n" 
के लिए
+0

यह बहुत अच्छा था, धन्यवाद! यह एक आकर्षण की तरह काम करता है - मुझे वापस जाना था और फिर से पढ़ना था कि अंतराल को नियमित अभिव्यक्ति में शामिल किया जाना चाहिए जिसे मैं खोज रहा हूं, मुझे याद आया कि जब मैंने शुरुआत में यह कोशिश की थी। – wonderfulthunk

+0

यह काम करना चाहिए: /.*fifth.*[#{EOL} ]*/ http://rubular.com/r/skalXLBXcQ देखें –

0

मुझे नहीं लगता कि आप grep को तर्क प्रदान कर सकते हैं; api पर आधारित है।

आप हमेशा एक विधि लिख सकते हैं। इस के साथ कुछ:

def new_grep(enum, pattern, lines) 
values = enum.grep(/pattern/).map do |x| 
    index = enum.index(x) 
    i = (index - lines < 0) ? 0 : index - lines 
    j = (index + lines >= enum.length) ? enum.length-1 : index + lines 
    enum[i..j] 
end 
return values.flatten.uniq 
end 
+0

यह भी काम कर सकता है, लेकिन मुझे वेन का जवाब जो मैं चाहता था उसके साथ और अधिक होने का जवाब मिला। – wonderfulthunk

2

धन्यवाद प्रासंगिक grep। मैंने सोचा कि मैं जोड़ सकता हूं, कि जब मैच शीर्ष या नीचे के पास आता है और आप अभी भी सभी लाइनों को चाहते हैं तो सभी CONTEXT_LINES लाइनों के बिना भी प्राप्त कर सकते हैं, तो आप को CONTEXT की परिभाषा निम्नानुसार बदल सकते हैं:

CONTEXT = "((?:.*#{EOL}){0,#{CONTEXT_LINES}})" 

डिफ़ॉल्ट रूप से, मैचों लालची हैं, इसलिए यदि हिस्सा या CONTEXT_LINES लाइनों के सभी उपलब्ध है, कि तुम क्या हड़पने करेंगे।

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