同じ値を持つ行の選択に問題があります。私のデータが大きすぎて、これを行ごとに実行できません。これを実行できるスクリプトを教えてください。
私のデータは次のとおりです。
ファイル名:temp
Start day hour end day hour Value
01/04/2000 22:00 01/05/2000 09:00 -9
01/05/2000 09:00 01/06/2000 09:00 -9
01/06/2000 09:00 01/07/2000 09:00 -9
01/07/2000 09:00 01/08/2000 09:00 -9
01/08/2000 09:00 01/09/2000 09:00 -9
01/09/2000 09:00 01/10/2000 09:00 -9
01/10/2000 09:00 01/11/2000 09:00 -9
01/11/2000 09:00 01/11/2000 21:30 -9
01/11/2000 22:30 01/12/2000 09:00 -9
01/12/2000 09:00 01/13/2000 09:00 -9
01/15/2000 09:00 01/16/2000 09:00 -9
01/16/2000 09:00 01/17/2000 09:00 -9
01/17/2000 09:00 01/18/2000 09:00 -9
01/18/2000 09:00 01/18/2000 22:45 -9
01/18/2000 22:50 01/19/2000 09:00 0.15
01/19/2000 09:00 01/20/2000 09:00 -9
01/20/2000 09:00 01/21/2000 09:00 -9
01/21/2000 09:00 01/22/2000 09:00 -9
01/22/2000 09:00 01/23/2000 09:00 -9
01/23/2000 09:00 01/24/2000 09:00 -9
01/24/2000 09:00 01/25/2000 09:00 -9
01/25/2000 09:00 01/26/2000 00:35 -9
01/26/2000 00:35 01/26/2000 09:00 -9
01/26/2000 09:00 01/27/2000 09:00 -9
たとえば、上記の2000年1月18日は、「開始日」として2回、「終了日」として2回表示されます。だから、01/18/2000
「開始日」または「終了日」の行を含めたいと思います。
上記データの出力は以下の通りです。
Start day hour end day hour Value
01/10/2000 09:00 01/11/2000 09:00 -9
01/11/2000 09:00 01/11/2000 21:30 -9
01/11/2000 22:30 01/12/2000 09:00 -9
01/17/2000 09:00 01/18/2000 09:00 -9
01/18/2000 09:00 01/18/2000 22:45 -9
01/18/2000 22:50 01/19/2000 09:00 0.15
01/25/2000 09:00 01/26/2000 00:35 -9
01/26/2000 00:35 01/26/2000 09:00 -9
01/26/2000 09:00 01/27/2000 09:00 -9
答え1
私が正しく理解したら、開始日または終了日が繰り返される行が欲しいでしょう。これにより、次のようになります。
awk 'NR==FNR{s[$1]++;e[$3]++;next}
FNR == 1 || s[$1]>1 || e[$3]>1' temp temp
これはファイルに2つのパスを作成することです。最初のパスでは開始日と終了日の発生回数を計算し、2番目のパスでは開始日または終了日の発生回数が1より大きい行を出力します。
答え2
開始日と終了日が同じ行である場合(前の行を参照しない場合):
perl -ne 'print if(m!^(\d{2}/\d{2}/\d{4})\s+\d{2}:\d{2}\s+\1!);' < file
^
行の始まり
(\d{2}/\d{2}/\d{4})
日付と店舗が一致します(参照できるように)\1
。
\s+\d{2}:\d{2}\s+
1 つ以上のスペース 2 桁のコロン 2 桁 次の 1 つ以上のスペース
\1
「逆参照」保存日
一致すればprint
ラインです。
答え3
私はあなたのニーズを満たすことを望むPerlスクリプトを書いています。例で提供されたデータがというファイルにあるとしますtemp
。
#!/usr/bin/perl
### ./timetract.pl
## 01/10/2000 09:00 01/11/2000 09:00 -9
## 01/11/2000 09:00 01/11/2000 21:30 -9
## 01/11/2000 22:30 01/12/2000 09:00 -9
## ...
## 01/17/2000 09:00 01/18/2000 09:00 -9
## 01/18/2000 09:00 01/18/2000 22:45 -9
## 01/18/2000 22:50 01/19/2000 09:00 0.15
# ...
## 01/25/2000 09:00 01/26/2000 00:35 -9
## 01/26/2000 00:35 01/26/2000 09:00 -9
## 01/26/2000 09:00 01/27/2000 09:00 -9
## 01/27/2000 09:00 01/28/2000 09:00 -9
use strict;
use warnings;
use feature qw( say );
open (my $fh, "<", "temp") || die "Can't open temp: $!";
my ($prevEndDate, @middleRow, $s1, $s2, $mRow) = "";
for my $cRow (<$fh>) {
chomp($cRow);
my @currentRow = split(/\s+/, $cRow);
next if $currentRow[0] =~ /Start/; # skip first row
## col1 col2 col3 col4 col5
## ---- ---- ---- ---- ----
## 01/27/2000 09:00 01/28/2000 09:00 -9
# identify that we're on the last row of a block that
# we're interested in, print it, reset & go to the next row
if ($currentRow[0] eq $prevEndDate && $s2) {
say $cRow;
$s1 = $s2 = 0; # reset states, get ready for next block
next;
}
# identify that we're in the middle of a block that
# we're interested in, so save current row as a middle row
if ($currentRow[0] ne $currentRow[2]) {
$prevEndDate = $currentRow[2];
@middleRow = @currentRow;
$mRow = $cRow;
next;
}
# identified beginning row of a block of rows that we're interested in
$s1 = 1 if ($prevEndDate eq $currentRow[0]);
# identified middle row of a block of rows that we're interested in
$s2 = 1 if ($s1 == 1 && $currentRow[0] eq $currentRow[2]);
say $mRow;
say $cRow;
}
close ($fh);
# vim: set ts=2 nolist :
実行すると、次の出力が表示されます。
$ ./timeextract.pl
01/10/2000 09:00 01/11/2000 09:00 -9
01/11/2000 09:00 01/11/2000 21:30 -9
01/11/2000 22:30 01/12/2000 09:00 -9
01/17/2000 09:00 01/18/2000 09:00 -9
01/18/2000 09:00 01/18/2000 22:45 -9
01/18/2000 22:50 01/19/2000 09:00 0.15
01/25/2000 09:00 01/26/2000 00:35 -9
01/26/2000 00:35 01/26/2000 09:00 -9
01/26/2000 09:00 01/27/2000 09:00 -9