sintassi corretta per grep: cerca una stringa, copia due righe sopra e traspone

4

Sono nuovo (2 giorni) su Linux e grep e sono bloccato qui. Scenario. Ho dati che durano più di 10 anni che ho fatto manualmente fino a quando non mi sono imbattuto in grep. Le cartelle sono di forma /yyyy/mm/dd i.e. giorno1, giorno2 fino alla fine del mese. Devo cercare una stringa specifica iteration 8 . Se trovato, quindi ho bisogno di copiare le 3 righe precedenti dalla riga in cui si trova iteration 8 . Quindi ho bisogno di trasporre in un file di output. Ecco come sto tentando di raggiungere il mio dilemma. Dal momento che non riesco a trasporre sto cercando di dividere le uscite quindi combinare in seguito. Per favore guidami su questo caso.

 for file in /filepath/snc* #adding full path
     do
      echo $file
       grep -r " Mean" $file | awk '{print  " " }'> mean.txt # to enable single columns for ease of manipulation later
       grep -r " RMS" $file | awk '{print  " " }' > rms.txt
       grep -r " o-c" $file | awk '{print  " "}' > o-c.txt
       grep -rl "iteration 8" $file > iteration.txt # to verify that the files are the correct ones
      done

paste iteration.txt o-c.txt mean.txt rms.txt > daily-summary.txt #the output file must be in this specific order
grep "iteration 8" daily-summary.txt | awk '{print  " "  " "  " "  " "  " " }' >> monthly-summary-path.txt

#grep -3 "iteration 8" daily-summary.txt  >> monthly-summary-file.txt # two lines before

rm mean.txt rms.txt std.txt

File di input di esempio:

            Mean    -78.6
            rms      1615
            o-c      1612.97456

iteration 8

File di output di esempio:

year month day o-c         mean  rms
2015   12   12  1612.97456 -78.6 1615
2015   12   11  1525.36589 -78.0 1642

=======================   
    
posta user3192045 22.12.2015 - 10:59

1 risposta

1

Questo creerà un report per un singolo mese:

#!/usr/bin/perl

use strict;
use warnings;

@ARGV == 1 || die($!);

my $realpath = 'realpath $ARGV[0]';
chomp($realpath);

opendir(my $dir, $realpath) || die($!);

my @files;

while(readdir($dir)) {
    -f "$realpath/$_" && push(@files, "$realpath/$_");
}

print("year\tmonth\tday\to-c\tmean\trms\n");

my @realpath_s = split("/", $realpath);

foreach my $file (sort(@files)) {
    open(my $in, $file) || die($!);

    while(<$in>) {
        if(/^\s*Mean/) {
            my @row;
            for(my $i = 0; $i < 3; $i++) {
                my @F = split(/\s/);
                push(@row, $F[2]);
                $_ = <$in>;
            }
            $_ = <$in>;
            my @F = split(/\s/);
            if($F[1] == 8) {
                $file =~ s/.*day//;
                print("$realpath_s[@realpath_s-2]\t$realpath_s[@realpath_s-1]\t$file\t$row[2]\t$row[0]\t$row[1]\n");
                last;
            }
        }
    }
}

print("\n=======================\n");

exit 0;

Salvalo, ad esempio, ~/script.pl e chiamalo passando il percorso ai rapporti di un mese:

perl ~/script.pl /path/to/2015/12

L'output verrà stampato sul terminale; puoi utilizzare un reindirizzamento per reindirizzare a un file:

perl ~/script.pl /path/to/2015/12 > ~/report_2015_12.txt

Dovrebbe essere abbastanza facile scrivere più chiamate in uno script Bash per creare rapporti annuali / decennali.

% tree
.
├── 2015
│   └── 12
│       ├── day1
│       ├── day2
│       └── day3
└── script.pl

2 directories, 4 files
% perl script.pl 2015/12
year    month   day o-c mean    rms
2015    12  1   1612.97456  -78.6   1615
2015    12  2   1612.97456  -79.6   1615
2015    12  3   1612.97456  -80.6   1615

=======================

Nell'esempio tutti i file in 2015/12 contengono una riga iteration 8 , quindi una riga viene stampata per ciascuno di essi.

    
risposta data kos 22.12.2015 - 15:23

Leggi altre domande sui tag