web-dev-qa-db-ja.com

grepの適切な構文:文字列を検索し、上の2行をコピーして転置します

Linuxとgrepが新しく(2日前)で、ここに残っています。シナリオ。 grepに出会うまで手動で行っていた10年以上続くデータがあります。フォルダーの形式は/yyyy/mm/ddです。つまり、day1、day2、月末までです。特定の文字列iteration 8を検索する必要があります。見つかった場合は、iteration 8が配置されている行から前の3行をコピーする必要があります。次に、出力ファイルに転置する必要があります。これが私のジレンマを達成しようとしている方法です。転置できないため、出力を分割してから結合します。このケースについて教えてください。

 for file in /filepath/snc* #adding full path
     do
      echo $file
       grep -r " Mean" $file | awk '{print $1 " " $2}'> mean.txt # to enable single columns for ease of manipulation later
       grep -r " RMS" $file | awk '{print $1 " " $2}' > rms.txt
       grep -r " o-c" $file | awk '{print $3 " "$4}' > 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 $3 " " $4 " " $5 " " $6 " " $7 " " $8}' >> 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

サンプル入力ファイル:

            Mean    -78.6
            rms      1615
            o-c      1612.97456

iteration 8

サンプル出力ファイル:

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

=======================   
3
user3192045

これにより、1か月分のレポートが作成されます。

#!/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;

たとえば、~/script.plに保存し、1か月のレポートへのパスを渡して呼び出します。

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

出力は端末に出力されます。リダイレクトを使用してファイルにリダイレクトできます:

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

Bashスクリプトで複数の呼び出しをスクリプト化して、年次/ 10年レポートを作成するのはかなり簡単です。

% 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

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

この例では、2015/12のすべてのファイルにiteration 8行が含まれているため、それぞれの行が出力されます。

1
kos