बैश: एक फ़ाइल से कुछ लाइनें कैसे प्राप्त करें और आउटपुट को दूसरी फ़ाइल में सहेजें [बंद]

Jan 17 2021

मेरे पास इस तरह की एक लॉग फाइल है

$ cat build.log
..........
[ 60% 60917/101076] AAPT2 compile ....
[ 60% 60918/101076] AAPT2 compile ....
[ 60% 60919/101076] AAPT2 compile ....
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####

नए पार्स किए गए लॉग की तरह कैसे उत्पन्न करें ताकि नई फ़ाइल लॉग का आउटपुट इस तरह हो:

$ cat parsed.log
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####

जैसे [ 60% 60920/101076]फ़ाइल के अंत तक केवल अंतिम प्रगति मिलती है , शायद grep, sed, या किसी भी चीज़ का उपयोग करके। धन्यवाद

जवाब

dawg Jan 17 2021 at 22:29

यहाँ एक प्रति है:

$ perl -0777 -lne 'print $1 if /(^\[[^[]*\z)/m' file

या एक पर्ल पाइप:

$ perl -E 'say reverse <>' file | perl -lpE 'if (/^\[/){ say; last}' | perl -E 'say reverse <>'

एक के लिए awkआप कर सकते हैं:

$ awk 'BEGIN{RS="\\["}END{print "[" $0}' file

बेशक, आप यह जान सकते हैं कि यदि विफलता हमेशा 3 रेखाएँ होती हैं, तो सबसे सरल उपयोग है tail:

$ tail -n 3 file

सभी प्रिंट:

[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1
WilliamPursell Jan 17 2021 at 17:57
$ cat build.log ........ [ 60% 60917/101076] AAPT2 compile .... [ 60% 60918/101076] AAPT2 compile .... [ 60% 60919/101076] AAPT2 compile .... [ 60% 60920/101076] AAPT2 compile .... ninja: build stopped: subcommand failed. 21:41:22 ninja failed with: exit status 1 $ awk '$2 != n[2]{print p} {p = $0; split(p,n,FS)} END{print p}' build.log
........
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

awkइस तरह की चीज़ के लिए सही उपकरण है। यहां, हम जांचते हैं कि क्या दूसरा फ़ील्ड पिछली पंक्ति के दूसरे फ़ील्ड से मेल खाता है और यदि ऐसा है तो प्रिंट करें। फिर पिछली पंक्ति को स्टोर करें और दोहराएं। हमेशा इनपुट की अंतिम लाइन प्रिंट करें।

potong Jan 17 2021 at 18:07

यह आपके लिए काम कर सकता है (GNU sed):

sed '/^\[/h;//!H;$!d;x' file

यदि कोई लाइन [इसे होल्ड स्पेस में संग्रहीत करना शुरू कर देती है (पहले से कुछ भी लिखती है)।

ओथेवाइज, वर्तमान लाइन को होल्ड स्पेस में जोड़ता है।

अंतिम को छोड़कर सभी लाइनें हटाएं।

फ़ाइल के अंत में, होल्ड स्पेस पर स्वैप करें और इसकी सामग्री प्रिंट करें।

IdrissNeumann Jan 17 2021 at 18:15

यदि आप लाइनों के क्रम को बदलने के बिना इस तरह के फिल्टर का प्रदर्शन करना चाहते हैं तो आप कभी-कभी भाग्यशाली नहीं होते हैं। और उन पंक्तियों अपनी फ़ाइल की शुरुआत में लिखा है, तो नहीं कर रहे हैं, या अंत में: tac, sortऔर uniqसही उपकरण नहीं होगा।

यहाँ एक समाधान का उपयोग कर रहा है awk:

$ awk 'function push(a,e) { a[length(a)+1] = e } BEGIN {split("", lines); to_replace="toreplace"; exists=0} {if ($0 ~ "^\\[ [0-9]+%"){ll=$0; if (exists <= 0) {exists++; push(lines,to_replace)}} else {push(lines, $0)}} END {for (e in lines){if (lines[e] == to_replace) {print ll} else {print lines[e]}}}' test.log 
..........
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####

पठनीय और समझाया गया संस्करण:

# a function to append an element to an array dynamically
function push(a,e) { 
  a[length(a)+1] = e 
} 

BEGIN {
  split("", lines); # initializing an array
  to_replace="toreplace"; # you can change the replace key if you want
  exists=0
} 

{
  if ($0 ~ "^\\[ [0-9]+%"){ # matching all percentages/progression lines, regardless of their values ll=$0; 
    if (exists <= 0) {
      exists++; 
      push(lines, to_replace)
    }
  } else {
    push(lines, $0)
  }
}

END {
  for (e in lines) {
    if (lines[e] == to_replace) {
      print ll
    } else {
      print lines[e]
    }
  }
}

विलियम पर्सल समाधान के साथ अंतर तब है जब आपके प्रतिशत बढ़ रहे हैं। आइए इस मामले में व्यवहार का अंतर देखें:

$ cat test.log 
..........
[ 60% 60917/101076] AAPT2 compile ....
[ 60% 60918/101076] AAPT2 compile ....
[ 60% 60919/101076] AAPT2 compile ....
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####
$ awk 'function push(a,e) { a[length(a)+1] = e } BEGIN {split("", lines); to_replace="toreplace"; exists=0} {if ($0 ~ "^\\[ [0-9]+%"){ll=$0; if (exists <= 0) {exists++; push(lines,to_replace)}} else {push(lines, $0)}} END {for (e in lines){if (lines[e] == to_replace) {print ll} else {print lines[e]}}}' test.log 
..........
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####
$ awk '$2 != n[2]{print p} {p = $0; split(p,n,FS)} END{print p}' test.log 
..........
[ 60% 60919/101076] AAPT2 compile ....
[ 61% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####

तो आप या तो यह चुन सकते हैं कि यदि आप केवल अंतिम प्रगति पंक्ति रखना चाहते हैं, भले ही प्रतिशत समान न हो या यदि आप केवल उन पंक्तियों को फ़िल्टर करना चाहते हैं जिनमें एक ही प्रतिशत कई बार है।

Enlico Jan 17 2021 at 18:47

यदि यह गारंटी है कि पहली लाइन जिसे आप शुरू करना चाहते हैं [, तो यह अंतिम पंक्ति है , जिसके बाद आप यह कर सकते हैं, जो अनिवार्य रूप से फाइल की शुरुआत से लेकर अंतिम [लाइन लाइन द्वारा एकल के साथ पूर्ववर्ती सब कुछ बदल देता है [:

sed -z 's/.*\n\[/[/' file
EdMorton Jan 17 2021 at 22:50

...अपने नमूना इनपुट के प्रारंभ में रेखा मान लेना अधिक अग्रणी [...] ...रेखाओं का प्रतिनिधित्व करता है :

$ awk '/^\[/{p=$0 ORS; next} {print p $0; p=""}' build.log
[ 60% 60920/101076] AAPT2 compile ....
ninja: build stopped: subcommand failed.
21:41:22 ninja failed with: exit status 1

#### failed to build some targets (17:26 (mm:ss)) ####

यदि वह धारणा गलत है, तो कृपया अपने प्रश्न को एक न्यूनतम, पूर्ण , सत्यापित उदाहरण दिखाने के लिए संपादित करें - केवल प्रतिनिधि मूल्यों के साथ, ...एस नहीं ।