Bash: Bir dosyadan bazı satırlar nasıl alınır ve çıktı başka bir dosyaya nasıl kaydedilir [kapalı]

Jan 17 2021

Bunun gibi bir günlük dosyam var

$ 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)) ####

Yeni bir ayrıştırılmış günlükler gibi nasıl oluşturulur, böylece yeni dosya günlüğünün çıktısı şu şekildedir:

$ 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)) ####

Örneğin [ 60% 60920/101076]grep, sed veya başka bir şey kullanarak dosyanın sonuna kadar sadece son ilerlemeyi almak gibi . teşekkür ederim

Yanıtlar

dawg Jan 17 2021 at 22:29

İşte bir perl:

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

Veya bir perl borusu:

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

Bir için awkşunları yapabilirsiniz:

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

Elbette, arıza her zaman 3 satır ise, en basitinin sadece kullanım olduğunu biliyor olabilirsiniz tail:

$ tail -n 3 file

Tüm baskı:

[ 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

awkbu tür şeyler için doğru araçtır. Burada 2. alanın bir önceki satırın 2. alanıyla eşleşip eşleşmediğini kontrol edip, uyuyorsa yazdırıyoruz. Ardından önceki satırı kaydedin ve tekrarlayın. Her zaman girişin son satırını yazdırın.

potong Jan 17 2021 at 18:07

Bu sizin için işe yarayabilir (GNU sed):

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

Bir satır başlarsa, [onu ayırma alanında saklayın (daha önce oradaki herhangi bir şeyin üzerine yazın).

Aynı şekilde, mevcut satırı muhafaza alanına ekleyin.

Sonuncu hariç tüm satırları silin.

Dosyanın sonunda, saklama alanına geçin ve içeriğini yazdırın.

IdrissNeumann Jan 17 2021 at 18:15

Hatların sırasını değiştirmek zorunda kalmadan bu tür bir filtre uygulamak istiyorsanız, bazen şanslı değilsiniz. Ve bu satırları dosyanın başında yazılmıştır, veya sonunda değilse: tac, sortve uniqdoğru araçları olmaz.

İşte kullanarak bir çözüm 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)) ####

Okunabilir ve açıklanmış versiyon:

# 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]
    }
  }
}

William Pursel çözümlerinin farkı , yüzdelerin artmasıdır. Bu durumda davranış farkını görelim:

$ 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)) ####

Dolayısıyla, yüzde aynı olmasa bile yalnızca son ilerleme çizgisini korumak isteyip istemediğinizi veya yalnızca aynı yüzdeye sahip satırları birden çok kez filtrelemek isteyip istemediğinizi seçebilirsiniz.

Enlico Jan 17 2021 at 18:47

Çıkmak istediğiniz ilk satırın [, başlayan son satır olduğu garanti ediliyorsa, bunu yapabilirsiniz; bu, esasen dosyanın başlangıcından sonuncusuna kadar her şeyi [bir satır sonu ile değiştirir [:

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

...Örnek girişinizin başındaki çizginin daha fazla öncü [...] ...satırı temsil ettiğini varsayarsak :

$ 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)) ####

Bu varsayım yanlışsa, lütfen sorunuzu minimal, eksiksiz , doğrulanabilir bir örnek gösterecek şekilde düzenleyin - yalnızca temsili değerleri olan, ...s değil .