कारण क्यों
tac file | grep foo | head -n 1
पहले मैच में रोक नहीं है क्योंकि बफरिंग है।
आम तौर पर, head -n 1
एक पंक्ति को पढ़ने के बाद बाहर निकलता है। तो grep
एक SIGPIPE प्राप्त करना चाहिए और साथ ही साथ अपनी दूसरी पंक्ति लिखते ही बाहर निकलना चाहिए।
लेकिन क्या होता है क्योंकि इसका उत्पादन एक टर्मिनल पर नहीं जा रहा है, grep
यह बफर करता है। यही है, यह तब तक नहीं लिख रहा है जब तक कि यह पर्याप्त नहीं जमा हो गया है (जीएनयू ग्रीप के साथ मेरे परीक्षण में 4096 बाइट्स)।
इसका मतलब यह है कि grep
डेटा के 8192 बाइट्स लिखे जाने से पहले यह बाहर नहीं निकलेगा, इसलिए संभवत: यह कुछ लाइनें हैं।
जीएनयू के साथ grep
, आप इसे जल्दी से बाहर कर सकते हैं, --line-buffered
जिसके उपयोग से यह बताता है कि जैसे ही वे एक टर्मिनल पर जाते हैं या नहीं, वे लाइनों को लिखते हैं। तो grep
यह दूसरी लाइन पर बाहर निकलता है।
लेकिन जीएनयू के साथ grep
, आप -m 1
इसके बजाय उपयोग कर सकते हैं जैसा कि @terdon ने दिखाया है, जो पहले मैच में बाहर निकलने से बेहतर है।
यदि आपका grep
GNU नहीं है 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
लेकिन उन सभी मैचों को खोजने का मतलब है और केवल आखिरी को प्रिंट करना है।