날짜 표현에 대한 도움이 필요합니다 - csv 파일의 AWK

날짜 표현에 대한 도움이 필요합니다 - csv 파일의 AWK

상태:csv 파일에는 다양한 날짜 형식의 날짜 열이 있으며 이를 명시적인 날짜 형식(예: +"%m-%d-%Y")으로 변환하고 싶습니다.

파일 데이터 예:파일 이름 = Date_Test_new.csv

3/29/2019, Test, "I am new to, Unix", 04-05-2023
03/29/19, Test, "I am new to, Unix", 04-5-2023
Apr-29-2019, Test, "I am new to, Unix", "Apr-01-2019"
3/29/2019, Test, "I am new to, Unix", "Apr-01-2019"


**Source Date formats**
DD-MMM-YY -> 08-Sep-23

DD-MMM-YYYY -> 08-Sep-2023

MM/DD/YY -> 09/08/23

MM/DD/YYYY -> 09/08/2023

MM-DD-YYYY -> 09-08-2023

YYYYMMDD -> 20230908

DDMMMYY -> 08Sep23

원하는 출력

03-29-2019,Test, "I am new to, Unix", 04-05-2023
03-29-2019, Test, "I am new to, Unix", 04-05-2023
04-29-2019, Test, "I am new to, Unix", 04-01-2019
03-29-2019, Test, "I am new to, Unix", 04-01-2019

시도했지만 구문 오류가 발생합니다.

awk -F ',' '$1="date -d "$1" +"%m-%d-%Y" " ' Date_Test_new.csv > New_Output.csv

즉, 파일에 있는 전체 날짜 형식 열을 다른 날짜 형식으로 변환하려면 어떻게 해야 합니까?

어떤 도움이라도 나에게는 훌륭한 학습 경험이 될 것입니다. 감사해요

답변1

실제 데이터가 유효한 CSV 형식, 즉 필드로 구분된 쉼표 뒤에 공백이 없다고 가정하고 GNU awk를 사용 하고 3rg arg를 사용하여 다음을 수행 FPAT합니다 .gensub()match()

$ cat tst.awk
BEGIN {
    split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec",tmp)
    for (i in tmp) {
        mths[tmp[i]] = i
    }
    FPAT = "[^,]*|(\"([^\"]|\"\")*\")"
    OFS = ","
}
{
    for ( i=1; i<=NF; i++ ) {
        val = gensub(/^"|"$/,"","g",$i)

        day = mth = yr = 0
        if ( match(val,/^([0-9]{1,2})-([[:alpha:]]{3})-([0-9]{2}|[0-9]{4})$/,d) ) {
            # D-MMM-YY or DD-MMM-YY or ...YYYY
            day = d[1]
            mth = mths[d[2]]
            yr  = d[3]
        }
        else if ( match(val,/^([[:alpha:]]{3})-([0-9]{1,2})-([0-9]{2}|[0-9]{4})$/,d) ) {
            # MMM-D-YY or MMM-DD-YY or ...YYYY
            day = d[2]
            mth = mths[d[1]]
            yr  = d[3]
        }
        else if ( match(val,/^([0-9]{1,2})\/([0-9]{1,2})\/([0-9]{2}|[0-9]{4})$/,d) ) {
            # M/D/YY or M/DD/YY or MM/D/YY or MM/DD/YY or ...YYYY
            day = d[2]
            mth = d[1]
            yr  = d[3]
        }
        else if ( match(val,/^([0-9]{1,2})-([0-9]{1,2})-([0-9]{2}|[0-9]{4})$/,d) ) {
            # M-D-YY or M-DD-YY or MM-D-YY or MM-DD-YY or ...YYYY
            day = d[2]
            mth = d[1]
            yr  = d[3]
        }
        else if ( match(val,/^([0-9]{2})([[:alpha:]]{3})([0-9]{2})$/,d) ) {
            # DDMMMYY
            day = d[1]
            mth = mths[d[2]]
            yr  = d[1]
        }
        else if ( match(val,/^([0-9]{4})([0-9]{2})([0-9]{2})$/,d) ) {
            # YYYYMMDD
            day = d[3]
            mth = d[2]
            yr  = d[1]
        }

        if ( length(yr) == 2 ) {
            yr = "20" yr
        }

        day += 0
        mth += 0
        yr  += 0

        if ( (1 <= day) && (day <= 31) &&
             (1 <= mth) && (mth <= 12) &&
             (1 <=  yr) && (yr  <= 9999) ) {
            $i = sprintf("%04d-%02d-%02d", yr, mth, day)
        }
    }
    print
}

$ awk -f tst.awk Date_Test_new.csv
2019-03-29,Test,"I am new to, Unix",2023-04-05
2019-03-29,Test,"I am new to, Unix",2023-04-05
2019-04-29,Test,"I am new to, Unix",2019-04-01
2019-03-29,Test,"I am new to, Unix",2019-04-01

귀하가 나열한 모든 날짜 형식 등을 다루었지만 else if ( match(...) ) { ... }구문 분석할 수 있는 다른 형식에 대한 블록을 추가하기만 하면 됩니다.

match()일부 정규식을 완화하여 좀 더 유사한 호출을 병합하거나 더 잘 작동하는 경우 일부 정규식을 더 엄격하게 만들 수도 있습니다.

sprintf()원하는 출력 형식으로 변경하세요 . 하지만 계속 사용하는 것이 좋습니다.ISO 8601 날짜 형식, YYYY-MM-DD, 나는 이 날짜의 후속 처리를 용이하게 하기 위해 이것을 사용합니다.

원하는 경우 수표의 유효 날짜를 자유롭게 추가하거나 변경할 수 있습니다. 우리는 GNU awk를 사용하고 있으므로 원할 경우 각 블록의 입력 형식을 기억한 다음 하단에서 mktime()새로 생성된 날짜를 에포크 이후의 초로 변환한 다음 strftime()해당 초를 다시 원래 형식으로 변환하여 확인할 수 있습니다. 원래 날짜와 동일한 경우 정확한 일치 및 변환이 이루어지고 있는지 확실하게 확인하세요. 연습으로 남겨두세요... :-).

필드 구분 후 데이터에 공백이 있는 경우 ,:

$ cat file
3/29/2019, Test, "I am new to, Unix", 04-05-2023
03/29/19, Test, "I am new to, Unix", 04-5-2023
Apr-29-2019, Test, "I am new to, Unix", "Apr-01-2019"
3/29/2019, Test, "I am new to, Unix", "Apr-01-2019"

다음을 사용하여 유효한 CSV로 변환할 수 있습니다.

$ awk 'BEGIN{FS=OFS="\""} {for (i=1; i<=NF; i+=2) gsub(/, /,",",$i)} 1' file
3/29/2019,Test,"I am new to, Unix",04-05-2023
03/29/19,Test,"I am new to, Unix",04-5-2023
Apr-29-2019,Test,"I am new to, Unix","Apr-01-2019"
3/29/2019,Test,"I am new to, Unix","Apr-01-2019"

위의 모든 내용은 필드에 개행 문자가 포함될 수 없다고 가정합니다. 필드에 줄 바꿈이 포함되어 있으면 더 많은 작업이 필요합니다. awk를 사용하여 CSV를 처리하는 방법에 대한 자세한 내용은 다음을 참조하세요.awk를 사용하여 csv를 효율적으로 구문 분석하는 가장 강력한 방법은 무엇입니까.

관련 정보