![날짜 문자열 형식 변경](https://linux55.com/image/64723/%EB%82%A0%EC%A7%9C%20%EB%AC%B8%EC%9E%90%EC%97%B4%20%ED%98%95%EC%8B%9D%20%EB%B3%80%EA%B2%BD.png)
잘못된 날짜로 가득 찬 파일의 형식을 다시 지정하는 방법을 찾으려고 합니다. 소스는 다음과 같습니다.
{"_id":"","timestamp":"Mon Apr 20 08:30:55 +0000 2015"}
{"_id":"","timestamp":"Mon Apr 20 08:32:25 +0000 2015"}
{"_id":"","timestamp":"Mon Apr 20 08:35:39 +0000 2015"}
이와 같은 항목이 약 3백만 개 있습니다. 타임스탬프를 ISO-8601 형식으로 지정해야 합니다. YYYY-MM-DDTHH:mm:ss.mmm<+/-Offset>
나는 이것을 시도했고 작동합니다 :
date -d "Mon Apr 20 08:35:39 +0000 2015" +%FT%T%z
300만 개의 항목을 모두 수동으로 처리하지는 않을 것이므로 이 목적으로 sed를 사용하는 방법을 생각해 보았습니다.
cat input.json | sed "s|\"timestamp\":\"\(.*\)\"|\"timestamp\":\"$(date -d \1 +%FT%T%z)\"|g" > output.json
그러나 매번 동일한(잘못된) 출력이 인쇄됩니다 2015-05-08T01:00:00+0000
. 이 딜레마를 해결하는 데 도움을 줄 수 있는 사람이 여기 있습니까?
답변1
sed
이 목적 으로 사용될 수 있지만 awk
더 자연스럽습니다.
awk -F'"' -v OFS='"' '$8 {cmd="date -d \""$8"\" +%FT%T%z"; cmd | getline $8; close(cmd)} 1' input.json
{"_id":"","timestamp":"2015-04-20T01:30:55-0700"}
{"_id":"","timestamp":"2015-04-20T01:32:25-0700"}
{"_id":"","timestamp":"2015-04-20T01:35:39-0700"}
위 이미지는 -7:00시간의 오프셋을 보여줍니다. 이는 시스템의 기본 시간대를 반영합니다. 쉘 변수를 변경하면 TZ
기본값이 변경됩니다.
어떻게 작동하나요?
-F'"' -v OFS='"'
그러면 입력 및 출력 필드 구분 기호가 로 설정됩니다
"
.$8 {cmd="date -d \""$8"\" +%FT%T%z"; cmd | getline $8; close(cmd)}
"
필드 구분 기호 로 날짜는 필드 번호 8입니다. 그러면 올바른 명령을 사용하여 문자열이 생성된date
다음 명령을 실행하여 업데이트된 필드 8에 출력을 캡처합니다.앞의 출력은
$8
필드 8에 null이 아닌 값이 있는 경우에만 이 섹션이 실행된다는 것을 의미합니다. 이를 통해 예를 들어 빈 라인이 방해받지 않고 통과할 수 있습니다.1
이것은 "이 줄을 인쇄하세요"에 대한 awk의 비밀스러운 속기입니다.
추가 큰따옴표 처리
필드 구분 기호로 사용하고 있기 때문입니다 "
. "
타임스탬프 앞에는 다양한 횟수가 있다고 가정합니다 . 이 경우 타임스탬프를 $(NF-1)
여덟 번째 필드가 아닌 두 번째에서 마지막 필드로 호출해야 합니다 $8
. 이 경우:
awk -F'"' -v OFS='"' '$8 {cmd="date -d \""$(NF-1)"\" +%FT%T%z"; cmd | getline $(NF-1); close(cmd)} 1' input.json
날짜 필드에 사용자 정의 형식 추가
$ awk -F'"' -v OFS='"' '$8 {cmd="date -d \""$(NF-1)"\" +%FT%T%z"; cmd | getline $(NF-1); close(cmd);$(NF-1)="{$date:" $(NF-1) "}"} 1' input.json
{"_id":"","timestamp":"{$date:2015-04-20T01:30:55-0700}"}
{"_id":"","timestamp":"{$date:2015-04-20T01:32:25-0700}"}
{"_id":"","timestamp":"{$date:2015-04-20T01:35:39-0700}"}
답변2
답변3
입력이 표시한 대로 정확하게 형식화된다는 것을 보장할 수 있다면 정확히 그렇게 할 수 있습니다 sed
. 이것은 약간의 무차별 대입입니다.
sed \
-e 's/"timestamp":"... Jan/"timestamp":"01/' \
-e 's/"timestamp":"... Feb/"timestamp":"02/' \
-e 's/"timestamp":"... Mar/"timestamp":"03/' \
-e 's/"timestamp":"... Apr/"timestamp":"04/' \
-e 's/"timestamp":"... May/"timestamp":"05/' \
-e 's/"timestamp":"... Jun/"timestamp":"06/' \
-e 's/"timestamp":"... Jul/"timestamp":"07/' \
-e 's/"timestamp":"... Aug/"timestamp":"08/' \
-e 's/"timestamp":"... Sep/"timestamp":"09/' \
-e 's/"timestamp":"... Oct/"timestamp":"10/' \
-e 's/"timestamp":"... Nov/"timestamp":"11/' \
-e 's/"timestamp":"... Dec/"timestamp":"12/' \
-e 's/"timestamp":"\(..\) \(..\) \(..:..:..\) \(.....\) \(....\)"/"timestamp":"\5-\1-\2T\3\4"/' \
input.json > output.json
월 이름을 월 이름으로 바꾼 다음 (현재) 모든 숫자로 구성된 날짜 문자열을 분할하고 해당 부분을 원하는 순서로 다시 합칩니다. 밀리초를 추가하려면 와 사이에 .000
삽입하세요 .\3
\4