कारण क्यों
tac file | grep foo | head -n 1
पहले मैच में रोक नहीं है क्योंकि बफरिंग है।
आम तौर पर, head -n 1एक पंक्ति को पढ़ने के बाद बाहर निकलता है। तो grepएक SIGPIPE प्राप्त करना चाहिए और साथ ही साथ अपनी दूसरी पंक्ति लिखते ही बाहर निकलना चाहिए।
लेकिन क्या होता है क्योंकि इसका उत्पादन एक टर्मिनल पर नहीं जा रहा है, grepयह बफर करता है। यही है, यह तब तक नहीं लिख रहा है जब तक कि यह पर्याप्त नहीं जमा हो गया है (जीएनयू ग्रीप के साथ मेरे परीक्षण में 4096 बाइट्स)।
इसका मतलब यह है कि grepडेटा के 8192 बाइट्स लिखे जाने से पहले यह बाहर नहीं निकलेगा, इसलिए संभवत: यह कुछ लाइनें हैं।
जीएनयू के साथ grep, आप इसे जल्दी से बाहर कर सकते हैं, --line-bufferedजिसके उपयोग से यह बताता है कि जैसे ही वे एक टर्मिनल पर जाते हैं या नहीं, वे लाइनों को लिखते हैं। तो grepयह दूसरी लाइन पर बाहर निकलता है।
लेकिन जीएनयू के साथ grep, आप -m 1इसके बजाय उपयोग कर सकते हैं जैसा कि @terdon ने दिखाया है, जो पहले मैच में बाहर निकलने से बेहतर है।
यदि आपका grepGNU नहीं है grep, तो आप उपयोग कर सकते हैं sedया awkइसके बजाय। लेकिन tac जीएनयू कमांड होने के नाते, मुझे संदेह है कि आपको एक सिस्टम मिलेगा tacजहां grepजीएनयू नहीं है grep।
tac file | sed "/$pattern/!d;q" # BRE
tac file | P=$pattern awk '$0 ~ ENVIRON["P"] {print; exit}' # ERE
कुछ प्रणालियों को tail -rवही करना पड़ता है जो GNU tacकरता है।
ध्यान दें कि, नियमित (खोज योग्य) फ़ाइलों के लिए, tacऔर tail -rकुशल हैं क्योंकि वे फ़ाइलों को पीछे की ओर पढ़ते हैं, वे फ़ाइल को पूरी तरह से मेमोरी में नहीं पढ़ते हैं इससे पहले कि इसे पीछे की तरफ प्रिंट किया जा सके (जैसा कि @ एसएलएम का sed दृष्टिकोण या tacगैर-नियमित फ़ाइलों पर होगा) ।
उन प्रणालियों पर जहां न तो उपलब्ध हैं tacऔर न ही tail -rकेवल प्रोग्रामिंग भाषाओं जैसे perlया उपयोग के साथ पिछड़े-पठन को लागू करने के लिए विकल्प हैं :
grep -e "$pattern" file | tail -n1
या:
sed "/$pattern/h;$!d;g" file
लेकिन उन सभी मैचों को खोजने का मतलब है और केवल आखिरी को प्रिंट करना है।