要するに、私の主な問題は、日付に基づいて記録を印刷することです。あるフィールドが他のフィールドと 1 か月もない差があります。。すべての日付が含まれています。月一年滞在。
|
具体的には、次の基準を満たす場合は、パイプ()で区切られた108のフィールドを含むファイルからレコードを抽出しようとします。
日付フィールド14と61には10月のデータを含める必要があります。 #Resolved
日付フィールド 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;
}
}