説明する

説明する

要するに、私の主な問題は、日付に基づいて記録を印刷することです。あるフィールドが他のフィールドと 1 か月もない差があります。。すべての日付が含まれています。月一年滞在。

|具体的には、次の基準を満たす場合は、パイプ()で区切られた108のフィールドを含むファイルからレコードを抽出しようとします。

  1. 日付フィールド14と61には10月のデータを含める必要があります。 #Resolved

  2. 日付フィールド 14 は、日付フィールド 15 + 1 か月未満でなければなりません ($15 < $14+ 1 か月) #Unresolved

私のコード:

awk -F'|' '{ if ($14 ~ /10-..-2016/ && $61 ~ /10-..-2016/ && $15< date -d '$14 1 month'  ) print $0}' <input >output

機能しない部分はです$15< date -d '$14 1 month'。主な問題はMM-DD-YYYY形式で、2つのフィールドを比較しています。

入力(ヘッダーがなく、サンプルデータを説明するのに役立つように使用します。勇敢な記録された理由を除く):
.....|field14|field15|.....|Field61|.....
1.....|10-21-2016|11-二十三-2016|.....|2016年10月25日|.....
2.....|2016年10月21日|2016年11月20日|.....|11-2016年2月25日|.....
3.....|2016年10月21日|2016年11月19日|.....|2016年10月25日|... ..
4... ..|2016年10月15日|2016年10月11日|.....|2016年10月25日|.....
5.....|2016年10月21日|10~19日-2016|.....|2016-10-25|.....
6.....|09-21-2016|09-19-2016|.....|10-25-2016|.....
必須出力 (タイ​​トルは説明用):
.....|field14|field15|. ...|Field61|.....
3.....|2016年10月21日|2016年11月19日|.....|2016年10月25日|....
4 .. ... |2016年10月21日|2016年11月15日|.....|2016年10月25日|.....

この問題をどのように解決できますか?

答え1

perl -F'[|]' -lane '
   ($m2, $d2, $y2, $m1, $d1, $y1) = map { split /-/ } @F[14,13];

   ($m2, $d2, $y2, $m1, $d1, $y1) =
   ($m1, $d1, $y1, $m2, $d2, $y2) if !($y2 > $y1 or $m2 > $m1 or $d2 > $d1);

   print if
      2 == grep /^10-\d{2}-\d{4}$/, @F[13,60]
                and
      (((12*($y2-$y1)+$m2-$m1) == 1 && ($d2 < $d1))
                    ||
          ((12*($y2-$y1)+$m2-$m1) == 0))
' yourfile

説明する

暗黙的な行読み取りループを設定し、パイプ"|"を使用して読み取った各行を分割して、区切り@F文字とインデックスで始まる配列を作成します。0

次に、後でコードで簡単に操作できるように、フィールドの月/年/日情報をスカラー変数14に入力します。15

これを行うときは、日付論理計算を簡素化するために、m2y2d2日付が常に日付よりも最新になるように少し調整してください。m1y1d1

最後に、次の4つの基準に従って現在のレコード、つまり行の印刷を判断することにしました。

  • 14番目の要素は$F[13]Octoberと日です。そして
  • 61番目の要素、つまりその月の日付でも$F[60]あります。Octoberそして
  • 2 つの日付は、年を考慮した用語を使用して 1 か月間隔であり、親日付(y2-y1)*12​​の日付 < 子日付の日付の場合は、月ごとにあります。または
  • これらの2つの日付は同じ年と月にあります=>とにかく両方とも1ヶ月以内です

答え2

各行に対してこれを実行することはdate非常に非効率的であり、日付計算を直接実行できるテキスト処理ツールを使用する方が良いでしょうperl。たとえば、次のようになります。

perl -MTime::Piece -F'[|]' -lane 'print if
   $F[13] =~ /10-..-2016/ && 
   $F[60] =~ /10-..-2016/ &&
   Time::Piece->strptime($F[14], "%m-%d-%Y") <
     Time::Piece->strptime($F[13], "%m-%d-%Y")->add_months(1)' file 

答え3

GNU awk実際には時間関数が組み込まれているので、それは難しくありません。

$2 ~ /^10/ && $5 ~ /^10/ {
    split($2, t, "-");
    t1 = mktime(t[3] " " t[1] " " t[2] " 0 0 0");
    split($3, t, "-");
    t2 = mktime(t[3] " " t[1] " " t[2] " 0 0 0");
    if (t2 >= t1 && t2 - t1 <= 30*24*3600) {
        print;
    }
}

関連情報