AWK: 다른 레코드의 필드 결합

AWK: 다른 레코드의 필드 결합

반면 file:

2018-03-22 foo/bar/baz
2020-09-30 Lorem/ipsum/dolor
2021-10-01 yadda/yadda/yadda
2022-03-14 blah/blah/blah

(실제 파일에는 이와 같은 수천 줄이 포함되어 있습니다)

문자열을 얻는 방법2018-03-22_2022-03-14? 이는 레코드 1의 필드 1, 밑줄, 마지막 레코드의 필드 1을 연결한 것입니다.

나는 이것을 생각해 냈습니다 :

$ awk 'BEGIN{ORS="_"}NR==1{print $1} END{print $1}' file | sed 's/_$//'
2018-03-22_2022-03-14

작동하지만복잡하지 않은awksed파이프나 서브쉘 만 사용하거나 사용하지 않고 동일한 결과를 얻는 방법입니다. 실제로 그런 방법이 있나요?

답변1

전용 버전 sed:

sed 's/ .*//;1h;$!d;H;g;y/\n/_/' file
  • s/ .*//공백 뒤의 모든 항목을 제거하고 날짜만 유지하는 데 사용됩니다 .
  • 1h1공백 에 행 날짜 복사hold
  • $!d d마지막 줄을 제외한 모든 줄 삭제
  • 여기에 도착하면 마지막 행에 있으므로 H첫 번째 날짜가 포함된 이 행을 이전 공간에 추가한 다음 둘 다 패턴 공간에 복사합니다.g
  • 이제 남은 유일한 일은 삽입된 개행(추가로 인해)을 밑줄로 바꾸는 것입니다.y/\n/_/

(네 좀 짧네요)

답변2

이식성을 위해 이 섹션에서 구현 print $1(또는 사용 $anything) 하지 마십시오 END. 이 섹션의 해당 항목은 $0POSIX에 따라 정의되지 않은 동작이기 때문입니다. 일부 awks에서는 이 부분이 마지막 줄에서 읽은 첫 번째 필드의 값이 되고, 다른 경우에는 null이 되며, 다른 경우에는 다른 값일 수 있습니다.$1END$1END

모든 Unix 시스템의 모든 쉘에서 awk를 사용하십시오.

$ awk -v OFS='_' 'NR==1{beg=$1} {end=$1} END{print beg, end}' file
2018-03-22_2022-03-14

_또는 입력 파일이 비어 있으면 단일 파일을 인쇄하지 마세요.

awk -v OFS='_' 'NR==1{beg=$1} {end=$1} END{ if (NR) print beg, end}' file

위의 내용은 입력에 행이 1개만 있는 경우 해당 $1행 간에 동일한 값이 반복되기를 원한다고 가정합니다 _. 이것이 원하는 것이 아니라면 질문을 업데이트하여 이 사례에 대한 요구 사항을 명확히 하십시오.

답변3

출력 제어 의 경우 printf:

$ awk 'NR==1{printf("%s_", $1)}END{print $1}' f
2018-03-22_2022-03-14

답변4

대용량 파일을 처리하는 데 속도 가 느리기 때문에 대용량 입력 파일을 사용 head하는 것이 좋습니다 .tailawksed

$ cat input.txt
2018-03-22 foo/bar/baz
2020-09-30 Lorem/ipsum/dolor
2021-10-01 yadda/yadda/yadda
2022-03-14 blah/blah/blah
{ head -n1 input.txt && tail -n1 input.txt; } |
  cut -d ' ' -f1 | paste -sd _ -
2018-03-22_2022-03-14

관련 정보