टेक्स्ट फ़ाइल के एक निश्चित बिंदु से पाठ की पिछली 20 पंक्तियों को प्रिंट करें


0

वर्तमान में:

मैं स्क्रिप्टिंग में नया हूं, खुद को सिखाता हूं जैसे मैं साथ जाता हूं और यह मेरी पहली स्क्रिप्ट है जो मैं विकसित कर रहा हूं। मेरी स्क्रिप्ट क्या करने की कोशिश कर रही है, निर्दिष्ट फ़ाइल को देखें, "त्रुटि" शब्द को खोजने के लिए फ़ाइल को स्कैन करें। वर्तमान में यह तब "ERROR" से शेष फ़ाइल को आउटपुट फ़ाइल में प्रिंट करता है।

संकट:

किसी फ़ाइल में शब्द "ERROR" को खोजने के बाद, मैं "ERROR" शब्द से पाठ की पिछली 20 पंक्तियों को आउटपुट फ़ाइल में कैसे प्रिंट कर सकता हूं और "ERROR" बिंदु से शेष फ़ाइल को उसी आउटपुट फ़ाइल में जोड़ सकता हूं?

संभावित समाधान?

क्या मैं ऐसा करने के लिए किसी प्रकार के लूप का उपयोग करूंगा? मेरे पास यह कोड है कि मेरे सिर में = यह कैसे काम करना है लेकिन यह सुनिश्चित नहीं है कि वास्तव में इसे कैसे लागू किया जाए। क्या कोई मुझे सलाह दे सकता है या बता सकता है कि क्या ऐसा करने का कोई बेहतर तरीका है?

स्क्रिप्ट:

my $file_handle = IO::File->new ('output','a') or die;

print $file_handle "*****************************\n";

while(<>) {

        print $file_handle $_ if(/.*ERROR/ .. /^XXX/);

        }

1
आपने इसे बैश के रूप में टैग किया है, लेकिन आपका कोड पर्ल है क्या आप एक पर्ल समाधान या बैश समाधान चाहते हैं?
Mr. Llama

जवाबों:


3

आप इसके साथ कर सकते हैं grep की -B ( --before-context ) विकल्प:

grep -B 20 error filename

1
हां! -B पहले के लिए, -A इसके बाद, -C पहले और बाद में ("संदर्भ") दोनों के लिए।
Mr. Llama

अब, अगली आवश्यकता, शेष फाइल को कैसे जोड़ा जाए?
glenn jackman

मै सुझाव दूंगा: grep -B 20 ERROR file && awk '/ERROR/ {p=1; next} p' file
glenn jackman

0

awk: मैं इस डेमो के लिए सिर्फ 5 लाइनें रख रहा हूं, "मान" को 20 तक समायोजित करें

{ seq 10; echo ERROR; seq 6; } |
awk -v keep=5 '
  /ERROR/ {
    for (i=keep; i>=1; i--) print lines[i]  # the stored lines
    print                                   # the current line
    while (getline > 0) print               # all the remaining lines
  }
  {
    # remember the previous "keep" lines.
    for (i=keep; i>1; i--)
      lines[i] = lines[i-1]
    lines[1] = $0
  }
'
6
7
8
9
10
ERROR
1
2
3
4
5
6

एक और दृष्टिकोण: फ़ाइल के माध्यम से 2 रीड लेता है, लेकिन यह स्पष्ट है, मुझे लगता है।

keep=20
lineno=$(sed -n '/ERROR/{=;q;}' file)
[[ -n $lineno ]] && sed -n "$((lineno-keep)),\$p" file

0

अगर मैं यह कर रहा हूँ

line=$(grep -m1 -n ERROR the_file | cut -f1 -d:)
if ((line <= 20)); then
  cat the_file;
else
  tail -n+$((line-20)) the_file
fi

जो उपयोग करता है grep मैच की लाइन नंबर प्राप्त करने के लिए "शो लाइन नंबर" · विकल्प के साथ, और फिर tail -n 20 वीं पिछली पंक्ति के साथ शुरुआत को प्रिंट करने के लिए, एक नकारात्मक शुरुआत लाइन नंबर से बचने के लिए सावधान रहें।

किसी भी अन्य भाषा में, समाधान पिछले 20 लाइनों के रीडिंग (शायद परिपत्र) बफर को रखना होगा। उदाहरण के लिए, awk में, एक गोलाकार बफर के साथ:

awk -v P=20 'found  { print; next }
             /ERROR/{ for (i=NR+1;i<=NR+P;++i) 
                        if (i%P in saved)
                          print saved[i%P]
                      found = 1
                    }
                    { saved[NR%P] = $0 }'
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.