파일의 첫 번째 열을 명령 출력으로 바꾸기

파일의 첫 번째 열을 명령 출력으로 바꾸기

이 질문에서Unix를 사용하여 열 복사 및 바꾸기

이 파일에서만 작동하는 솔루션을 구축하려고 합니다.

20070101 10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
20070102 10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
20070103 10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
20070104 10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

출력을 얻습니다.

01/01/2007  10.2317   79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007  10.2317   79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007  10.2317   79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007  10.2317   79.1638   8.1  26.0  19.6   0.0  15.5  94.1

다른 서류는 관련되지 않습니다.

그래서 첫 번째 열을 변환된 날짜로 바꾸고 싶습니다.

원본 파일에서 날짜를 얻었습니다.

$ awk '{print $1}' filedate.txt
20070101
20070102
20070103
20070104

그런 다음 다음을 사용하여 날짜 변환을 수행했습니다.

for i in $(awk '{print $1}' filedate.txt); do date -d "$i"  +%d/%m/%Y; done
01/01/2007
02/01/2007
03/01/2007
04/01/2007

하지만 변환된 날짜 값으로 파일의 첫 번째 열을 수정할 수는 없습니다. 나는 awk 대체()를 사용해 보았습니다 awk '{$1=$dt}1'.

for i in $(awk '{print $1}' filedate.txt); do dt=$(date -d "$i" +%d/%m/%Y) && awk '{$1=$dt}1' filedate.txt; done

그러나 루프가 포함되어 있으므로 출력이 원하는 대로 나오지 않습니다.

어떻게 해야 합니까 awk? 으로 동일한 작업을 수행할 수 있습니까 sed?

편집하다

다른 질문에 대한 의견에서 다음과 같은 방법을 보았습니다.sed

 sed 's,^\([0-9]\{4\}\)\([0-9]\{2\}\)\([0-9]\{2\}\),\3/\2/\1,'

date그런데 이제는 명령과 관련된 작업을 어떻게 수행하는지 궁금합니다 .

답변1

이미 존재하는 루프를 사용해 보겠습니다(실제로 살펴보진 않았지만 제대로 작동하는 것 같습니다).

for i in $(awk '{print $1}' filedate.txt); do date -d "$i"  +%d/%m/%Y; done

그럼 집어넣어다른 질문에 대한 내 대답약간 수정하세요:

for i in $(awk '{print $1}' filedate.txt); do date -d "$i"  +%d/%m/%Y; done |
paste - <( cut -d ' ' -f 2- filedate.txt )

결과:

01/01/2007      10.2317  79.1638   6.0  26.7  20.9   0.8  14.0  98.6
02/01/2007      10.2317  79.1638   5.6  26.5  20.8   1.9  13.6  98.0
03/01/2007      10.2317  79.1638   7.5  27.7  20.8   0.1  15.8  96.4
04/01/2007      10.2317  79.1638   8.1  26.0  19.6   0.0  15.5  94.1

루프 없이 더 짧게:

date -f <( cut -d ' ' -f 1 filedate.txt ) +"%d/%m/%Y" |
paste - <( cut -d ' ' -f 2- filedate.txt )

파이프가 없는 경우:

paste <( date -f <( cut -d ' ' -f 1 filedate.txt ) +"%d/%m/%Y" ) \
      <( cut -d ' ' -f 2- filedate.txt )

이러한 모든 예제에는 분명히 프로세스 대체를 이해하는 다른 쉘이 bash필요 합니다. 또한 GNU가 필요합니다.kshdate

바라보다다른 질문에 대한 내 대답작동 방식에 대한 설명입니다.

답변2

원하는 변환이 단지 기존 정보의 순서를 변경하는 것이라면 이 작업을 수행해 보는 것은 어떨까요?

awk '{ $1=sprintf("%02i/%02i/%04i",
     substr($1, 7, 2), substr($1, 5, 2), substr($1, 1, 4)) }1' file

첫 번째 필드에서 하위 문자열을 추출하고 이를 첫 번째 필드의 새 값으로 다시 조립한 다음 평소와 같이 전체 입력 줄을 인쇄합니다. (닫는 중괄호 뒤의 별도 문자는 1무조건 인쇄를 위한 표준 Awk 관용어입니다.)

기계가 완벽하게 읽을 수 있는 날짜를 다음과 같이 변환하면 후회할 수도 있습니다."사람이 읽을 수 있는"하지만 곧.

답변3

GNU awk()가 있는 경우 gawk명령 출력을 사용하여 열을 바꿀 수 있습니다.getline/변수/파이프 형식함수를 getline호출하는 방법 은 다음과 같습니다 .date

gawk '{"date +%d/%m/%Y -d" $1 | getline $1} 1' file

그러나 열의 날짜 형식만 변경하려는 경우 내장 함수 mktime와 함수를 사용하여 strftime로컬에서 변경할 수 있습니다.

gawk '{
  d = sprintf("%d %02d %02d 0 0 0", substr($1,1,4), substr($1,5,2), substr($1,7,2));
  t = mktime(d);
  $1 = strftime("%d/%m/%Y", t);
  } 1' file

이 경우 간단한 문자열 조작을 사용하여 원하는 변환을 수행할 수 있지만(이 방법은 모든 스타일에 적용됩니다 awk):

$ mawk '{$1 = sprintf("%02d/%02d/%02d", substr($1,7,2), substr($1,5,2), substr($1,1,4))} 1' file
01/01/2007 10.2317 79.1638 6.0 26.7 20.9 0.8 14.0 98.6
02/01/2007 10.2317 79.1638 5.6 26.5 20.8 1.9 13.6 98.0
03/01/2007 10.2317 79.1638 7.5 27.7 20.8 0.1 15.8 96.4
04/01/2007 10.2317 79.1638 8.1 26.0 19.6 0.0 15.5 94.1

답변4

GNU sed 명령의 eval 수정자를 사용하면 필요에 따라 날짜를 변환할 s수 있습니다 .date

sed -r 's|(\S+)(.*)|date -d \1 "+%d/%m/%y \2"|e'

대체된 표현식은 올바른 형식의 날짜 명령입니다. 수정자는 e이 명령이 각 행에 대해 실행되도록 하며 패턴 버퍼(및 출력)는 각 날짜 명령의 출력으로 대체됩니다.

관련 정보