부록

부록

다음 데이터 구조를 포함하는 CSV가 있습니다.

1111,2222,3333,4444,5555,6666,7777,2017-1-5 1:07:09,2017-1-5 1:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

날짜, 월, 일을 항상 2자리로 표시하고 싶습니다. 또한 시간 필드가 항상 2자리가 되기를 원합니다.

월/일/시간 필드가 단일 숫자인 경우(위의 예시 행에서처럼) 본질적으로 앞에 0을 추가하는 것입니다.

awk를 사용하면 어떻게 다음 결과를 얻을 수 있습니까?

1111,2222,3333,4444,5555,6666,7777,2017-01-05 01:07:09,2017-01-05 01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

답변1

훌륭한 텍스트 처리 도구는 다음과 같습니다.. 다음 예에서는 FreeBSD 11.1에서 일반 표준 awk를 사용합니다. GNU awk를 선호한다면 @RomanPerekhrest는 또 다른 답변에 우아한 솔루션을 제공합니다.

입력 내용은 쉼표로 구분됩니다. 따라서 awk매개변수를 사용하여 호출합니다 -F,.

그런 다음 이 명령문을 사용하여 열을 인쇄할 수 있습니다 print. $1첫 번째 열입니다. $2두 번째 칼럼입니다.

$ awk -F, '{ print $8 }' inputfile.csv
2017-1-5 1:07:09
2017-11-25 19:57:17

이는 각 행의 8번째 열을 제공합니다.

이는 작업하려는 날짜 필드입니다. 구분 기호를 설정하기 위해 명령줄 인수를 사용하는 대신 이를 스크립트의 일부로 설정할 수 있습니다. FS는 입력 구분 기호로 사용되고 OFS는 출력 구분 기호로 사용됩니다.

$ awk 'BEGIN { FS = "," } ; { print $8 }' inputfile.csv
2017-1-5 1:07:09
2017-11-25 19:57:17

날짜를 다룰 때 나는 일반적으로 date날짜가 올바르게 처리되는지 확인하기 위해 util을 사용하는 것을 선호합니다. 일반 또는 GNU awk를 사용하는지 걱정할 필요가 없습니다. 또한 날짜를 잘못 구문 분석하면 큰 실패가 발생합니다.

흥미로운 매개변수는 다음과 같습니다.

-j     Specify we do not want to set the date at all
-f     The format string we use for input
+      The format string we use for output

따라서 이 날짜를 실행하면 다음과 같습니다.

$ date -j -f "%Y-%m-%d %H:%M:%S" +"%Y-%m-%d %H:%M:%S" "2017-1-5 1:07:09"
2017-01-05 01:07:09

그런 다음 이것을 awk와 결합할 수 있습니다. 따옴표가 어떻게 생겼는지 확인하세요.탈출하다. 초보자에게는 이것이 가장 큰 걸림돌이 될 수 있습니다.

$ awk -F, '{ system("date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""$8"\"")}' inputfile.csv
2017-01-05 01:07:09
2017-11-25 19:57:17

시스템 호출은 올바른 것 같지만 불행하게도 반환 코드를 캡처하여 출력에 직접 인쇄할 수만 있습니다. 이를 방지하기 위해 이 패턴을 사용합니다 cmd | getline. 다음의 간단한 예에서는 현재 날짜를 mydate로 읽습니다.

$ awk 'BEGIN { cmd = "date"; cmd | getline mydate; close(cmd); print mydate }'
Thu Mar  1 16:26:15 CET 2018

BEGIN이 간단한 예에서는 입력이 없기 때문에 키워드를 사용합니다 .

이제 조금 확장해 보겠습니다.

awk 'BEGIN { FS=","; OFS=FS };
     { 
         cmd = "date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""$8"\"";
         cmd | getline firstdate;
         close(cmd);
         cmd = "date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""$9"\"";
         cmd | getline seconddate;
         close(cmd);
         print $1,$2,$3,$4,$5,$6,$7,firstdate,seconddate
     }' inputfile.csv

한 줄로 축소할 수 있습니다.

awk 'BEGIN {FS=",";OFS=FS};{cmd="date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""$8"\"";cmd | getline firstdate;close(cmd);cmd="date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""$9"\"";cmd | getline seconddate;close(cmd);print $1,$2,$3,$4,$5,$6,$7,firstdate,seconddate}' inputfile.csv

결과는 다음과 같습니다.

1111,2222,3333,4444,5555,6666,7777,2017-01-05 01:07:09,2017-01-05 01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

부록

여기서의 목적은 좋은 습관을 배우는 것이므로 이 답변을 업데이트하는 것이 좋습니다. 코드를 복제하는 것은 나쁜 습관입니다. 이 작업을 시작하면 모든 것을 함수로 나누어야 합니다. 아래 코드가 즉시 더 읽기 쉬워지는 것을 확인할 수 있습니다.

awk 'function convertdate(the_date) {
         cmd = "date -j -f \"%Y-%m-%d %H:%M:%S\" +\"%Y-%m-%d %H:%M:%S\" \""the_date"\"";
         cmd | getline formatted_date;
         close(cmd);
         return formatted_date
     }
     BEGIN { FS=","; OFS=FS };
     { 
         print $1,$2,$3,$4,$5,$6,$7,convertdate($8),convertdate($9)
     }' inputfile.csv

습관을 들이면 나중에 오류 처리를 도입하는 것이 얼마나 쉬운지 알게 될 것입니다.

답변2

GNU awk가 있으면 마지막 필드를 공백으로 구분된 필드로 변환할 수 있습니다.날짜 사양문자열을 입력한 다음 필요에 따라 다음을 사용하여 형식을 다시 지정합니다 strftime.

awk 'BEGIN{OFS=FS=","} {gsub(/[-:]/," ",$NF); $NF = strftime("%Y-%m-%d %H:%M:%S", mktime($NF))} 1' file
1111,2222,3333,4444,5555,6666,7777,2017-1-5 1:07:09,2017-01-05 01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

바라보다GNU awk 사용자 안내서: 시간 함수

답변3

간단한 GNUawk해결책:

awk 'BEGIN{ FS=OFS="," }{ gsub(/\<[0-9]\>/, "0&", $8); gsub(/\<[0-9]\>/, "0&", $9) }1' file
  • gsub(/\<[0-9]\>/, "0&", <field>)- 개별 한 자리 숫자만 대체/보충날짜 시간끈:
    • \<\>- 단어 경계입니다.
    • &- 정규식 패턴 일치의 정확한 하위 문자열을 나타냅니다.

산출:

1111,2222,3333,4444,5555,6666,7777,2017-01-05 01:07:09,2017-01-05 01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

답변4

이것날짜 도구패키지에는 시간/날짜 형식 데이터의 세부 정보를 처리하는 코드가 있습니다.

# Utility functions: print-as-echo, print-line-with-visual-space.
pe() { for _i;do printf "%s" "$_i";done; printf "\n"; }
pl() { pe;pe "-----" ;pe "$*"; }

pl " Input data file $FILE:"
head $FILE

pl " Expected output:"
cat $E

pl " Results, to standard format:"
dateutils.dconv -S <$FILE

pl " Results, to standard format, omitting the \"T\":"
dateutils.dconv -S -f '%F %T' <$FILE

생산:

-----
 Input data file data1:
1111,2222,3333,4444,5555,6666,7777,2017-1-5 1:07:09,2017-1-5 1:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

-----
 Expected output:
1111,2222,3333,4444,5555,6666,7777,2017-01-05 01:07:09,2017-01-05 01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

-----
 Results, to standard format:
1111,2222,3333,4444,5555,6666,7777,2017-01-05T01:07:09,2017-01-05T01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25T19:57:17,2017-11-25T19:58:54

-----
 Results, to standard format, omitting the "T":
1111,2222,3333,4444,5555,6666,7777,2017-01-05 01:07:09,2017-01-05 01:11:53
1111,2222,3333,4444,5555,6666,7777,2017-11-25 19:57:17,2017-11-25 19:58:54

이러한 시스템에서는:

OS, ker|rel, machine: Linux, 3.16.0-4-amd64, x86_64
Distribution        : Debian 8.9 (jessie) 
bash GNU bash 4.3.30
dateutils.dconv dconv 0.3.1

dconv에 대한 세부 정보:

dateutils.dconv Convert DATE/TIMEs between calendrical systems. (man)
Path    : /usr/bin/dateutils.dconv
Package : dateutils
Home    : http://www.fresse.org/dateutils
Version : 0.3.1
Type    : ELF 64-bit LSB shared object, x86-64, version 1 ( ...)
Help    : probably available with -h,--help
Home    : https://github.com/hroptatyr/dateutils (doc)

행운을 빕니다... 건배, drl

관련 정보