설명하다

설명하다

요컨대, 내 주요 문제는 날짜에 따라 기록을 인쇄하는 것입니다.한 필드가 다른 필드와 한 달도 채 안 되는 차이가 납니다.. 모든 날짜가 포함되어 있습니다.월 일 년체재.

|특히 다음 기준을 충족하는 경우 파이프( )로 구분된 필드 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 형식이며 두 필드를 비교하고 있습니다.

입력(헤더가 없으며 예시 데이터를 설명하는 데 도움이 되도록 사용합니다.용감한기록된 이유 제외):
.....|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그리고
  • 두 날짜는 연도를 고려한 용어를 사용하여 한 달 간격 (y2-y1)*12이며, 상위 날짜의 날짜 < 하위 날짜의 날짜인 경우 서로 월 내에 있습니다. 또는
  • 이 두 날짜는 같은 연도와 월에 있습니다 => 어쨌든 둘 다 한 달 내에 있습니다.

답변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;
    }
}

관련 정보