0

日付が含まれる複数の入力ファイルがありstrftime formatます。日付形式は入力変数の1つです。彼らのタイムラインが継続的であるかどうかを判断する必要があります。つまり、すべての入力ファイルの日付間隔が重ならない場合。

ファイル内のデータは連続しています。1つのファイルが1つの間隔であるようなものです。ファイルの最初の日付は間隔の左側にあり、最後の日付は間隔の右側にあります。

私の問題をよりよく示すために(データ形式%Y。%m。%d%H:%Mの例):

2つのデータファイルがあり、日付形式は%Y。%m。%d%H:%Mです。

data1.txt

2012.11.20 17:10 134343
2012.11.21 00:10 13323343
2012.12.22 15:10 13432323

data2.txt

2012.10.20 17:10 134343
2012.11.29 00:10 13333223343
2012.11.30 15:10 134323123

したがって、ファイル内の日付を確認できるように、data1.txtとdata2.txtは重複しています。

       2012.10.20         2012.11.20           2012.11.30                2012.12.22

data2.txt <=============================================>

                   data1.txt <===================================================>

私はこの問題をbashで実装していますが、いくつかのPerlフラグメントも歓迎します。

簡単な解決策が見つかりません。

ありがとう!

4

3 に答える 3

1

データの範囲のオーバーラップを計算することは、特に日付/時刻の値を処理する場合、簡単な作業ではありません。

モジュールをお勧めしTime::Piece::Rangeます。コアTime::Pieceモジュールを拡張して日付の範囲を処理し、overlapメソッドを備えています。

以下のコードrange_from_fileは、ファイルの名前を指定すると、ファイルの名前を含むすべてのレコードから日付を読み取り、オブジェクトの配列を作成する関数を実装しTime::Pieceます。配列がソートTime::Piece::Rangeされ、ソートされたリストの最初と最後の要素からオブジェクトが形成されて返されます。

2つのデータファイルでこのサブルーチンを呼び出すと、2つのTime::Piece::Rangeオブジェクトが生成され、メソッドの最後の呼び出しで、overlap2つのファイルに重複する日付/時刻が含まれるかどうかが判別されます。

サンプルファイルに適用するdata1.txtと、data2.txtこのコードはそれらが重複していることを確認します。

Time::Piece現在はコアモジュールですが、そうでTime::Piece::Rangeはなく、非コアモジュールもインストールする必要がDate::RangeあるDate::Simpleことに注意してください。ユーティリティはcpan依存関係を自動的にインストールしますが、Perlインストールを拡張する権限がない場合はこれが問題になる可能性があります。

use strict;
use warnings;

use Time::Piece::Range;

sub range_from_file {

  my $file = shift;
  open my $fh, '<', $file or die qq(Unable to open "$file" for reading);

  my @dates;
  while (<$fh>) {
    next unless /(\d+\.\d+\.\d+[ ]\d+:\d+)/;
    push @dates, Time::Piece->strptime($1, '%Y.%m.%d %H:%M');
  }

  return Time::Piece::Range->new((sort {$a <=> $b} @dates)[0,-1]);
}

my $r1 = range_from_file('data1.txt');
my $r2 = range_from_file('data2.txt');

print $r1->overlaps($r2) ? 'overlap' : 'distinct';

アップデート

コアモジュール以外は使用できず、strftimeフォーマットには固定長フィールド(など%B)しか含まれていないと想定している場合は、この代替手段をお勧めします。

データのデコードに使用する形式でrange_from_fileある追加の$formatパラメーターを取得するようにを変更しました。strftime

各レコードの最初の日付/時刻フィールドの長さは、現在の日付/時刻を指定された形式でフォーマットし、結果の文字列の長さを見つけることによって確立されます。

各ファイルレコードの先頭から同等の文字数が抽出され、ファイルの最初と最後の日付が配列に格納されます@dates

2つの日付はオブジェクトに変換され、匿名配列内のファイルの範囲Time::Pieceとして返されます。

新しいサブルーチンoverlapは、2つの範囲が重複しているかどうかをチェックします。最初の終わりが2番目の始まりの前にある場合、または2番目の終わりが最初の始まりの前にある場合、それらは分離されます。それ以外の場合、それらは重複します。

この場合も、このコードは、ファイル内のサンプルデータが重複data1.txtしていることを確認します。data2.txt

use strict;
use warnings;

use Time::Piece 'localtime';

sub range_from_file {

  my ($file, $format) = @_;
  open my $fh, '<', $file or die qq(Unable to open "$file" for reading);

  my $size = length Time::Piece->new->strftime($format);

  my @dates;
  while (<$fh>) {
    pop @dates if @dates >= 2;
    push @dates, substr $_, 0, $size;
  }

  my @range = map Time::Piece->strptime($_, $format), @dates;
  return \@range;
}

sub overlap {
  my ($r1, $r2) = @_;
  return not $r1->[1] < $r2->[0] or $r2->[1] < $r1->[0];
}

my $r1 = range_from_file('data1.txt', '%Y.%m.%d %H:%M');
my $r2 = range_from_file('data2.txt', '%Y.%m.%d %H:%M');

print overlap($r1, $r2) ? 'overlap' : 'distinct';
于 2012-06-12T12:34:17.200 に答える
0

さて、字句的に比較可能な形式に変換された日付(時間の有無は?)を比較する必要があります。これは、日付が一貫していることを意味しますYYYY.MM.DD(必要に応じて先行ゼロを使用します)。

#!/bin/bash
file1=$1
file2=$2
read -r start1 end1 < <(awk 'NR == 1 {print "$1-$2"} END {print "$1-$2"}' "$file1")
read -r start2 end2 < <(awk 'NR == 1 {print "$1-$2"} END {print "$1-$2"}' "$file2")
if [[ $start1 > $start2 || $end1 > $start2 ]]
then
    echo "Overlap!"
fi
于 2012-06-12T15:59:58.750 に答える
-1

perlでそれを行います。

2つのファイルが続く場合。その場合、file1の最後の行の日付がfile2の最初の行よりも前である場合にのみ、日付が重複します。

1)最初の行を取得します2)行を解析しますmy($ date1、$ data)= line(/ \ t /、$ line); または、Text:Csv 3)date1とdate2を解析しますmy($ Y1、$ m1、$ d1、$ H1、$ M1)= $ date =〜m!(\ d \ d \ d \ d)。(\ d \ d)。(\ d \ d)\ s +(\ d \ d):(\ d \ d)!gis; 4)エポック使用DateTimeを作成します。

$ dt1 = DateTime-> new(year => $ Y1、month => $ m1、day => $ d1、hour => $ h1、minute => $ m1、second => 0、nanosecond => 0、time_zone = >'UTC'、); 私の$epoch1= $ dt1-> epich; 私の$epoch2= $ dt2-> epich;

5)epoch1がepoch2よりも小さい場合は、問題ありません。

于 2012-06-12T12:49:13.980 に答える