다른 파일에 복사할 수 있도록 파일을 읽고 특정 문자열이 처음 나타나는 부분을 검색해야 합니다.

다른 파일에 복사할 수 있도록 파일을 읽고 특정 문자열이 처음 나타나는 부분을 검색해야 합니다.

다음과 같이 샘플 데이터 파일을 업데이트합니다.

empid;1001
empname;ABC
salary;3000
dept;ABC
age;24
dept;112
JOD;20170101
empid;A2001
salary;5000
dept;XYZ
age;27
JOD;20170303
age;92
empid;1002
empname;MAN
salary;11000
dept;SCI
age;30
dept;Geology
JOD;20180607
empid;1005
empname;NAME
salary;10200d
dept;XYZ
JOD;20161212

모든 속성을 검색하고 각 속성의 첫 번째 항목을 다른 파일에 복사해야 합니다. 출력은 다음과 같아야 합니다.

empid;1001
empname;ABC
salary;3000
dept;ABC
age;24
JOD;20170101
empid;2001
salary;5000
dept;XYZ
age;27
JOD;20170303
empid;1002
empname;MAN
salary;11000
dept;SCI
age;30
JOD;20180607
empid;1005
empname;NAME
salary;10200
dept;XYZ
JOD;20161212

dept두 번째 발생은 각 값 집합에 있는 경우 고려되어서는 안 됩니다.

empid,empname,salary,dept,age,JOD.

현재 다음 코드를 사용하고 있습니다.

awk -v FS=';' OFS=';'{ 
if ($1 == "empid" || $1 == "empname" || $1 == "salary" || $1 == "dept" || $1 == "age" || $1 == "JOD" ) print $0 }' FILE_NAME > NEW_FILE_NAME.

그러나 두 번째 등장 dept도 마찬가지입니다. 안내해 주세요.

답변1

Kusalananda가 정확하고 각 직원 기록이 line으로 시작한다고 가정하면 empid다음 awk명령이 작동합니다.

awk -F';' '$1=="empid" {delete a} !a[$1]++' input.txt > output.txt

이는 배열 변수를 사용하여 a발생한 속성 이름을 추적하고 아직 속성 이름이 발견되지 않은 경우에만 현재 줄을 인쇄합니다. 속성이 발견될 때 마다 empid배열이 재설정됩니다 .

좀 더 자세한 설명:

  • $1=="empid" {delete a}a새 레코드가 시작될 때마다 배열이 삭제됩니다.
  • !a[$1]++awk속기 표기법을 사용하면 1조건부 규칙의 바깥 부분은 "이 줄을 인쇄합니다"를 의미하고 0"인쇄하지 않음"을 의미합니다.
  • a[$1]++"발생 카운터"는 속성 이름의 각 값에 대해 증가하며 여기서는 "배열 인덱스"로 처리됩니다.
  • 평가 !a[$1]++첫 번째배열 항목의 현재 값이 0인지(즉, 속성이 아직 발견되지 않았는지) 확인하고, printtrue인 경우(부정 연산자 덕분에) 작업을 수행하고 카운터를 증가시킵니다.그 다음에(이는 C 스타일 프로그래밍 언어에서 접두사/접미사 증가가 작동하는 방식과 동일합니다.) 따라서 해당 속성이 아직 발견되지 않은 경우 인쇄되지만 이후 발생은 무시됩니다.

노트delete a명령문은 2012 POSIX 표준에서 허용하는 구문을 따르고 위의 내용은 GNU 및 GNU에 적용되지만 awkStéphane Chazelas mawknawk이 구문을 지원하지 않는 구현에 대해 다음과 같이 언급했습니다.

delete a

로 교체해야합니다

split("",a)

답변2

이는 다음과 같은 기본 아이디어이다.AdminBee의 솔루션, 약간 덜 우아하지만(아무 이유 없이 모든 값을 메모리에 저장합니다) 약간 짧습니다.

gawk -F';' '$1=="empid"{i=$2} ++a[i][$1]==1' file

첫 번째 필드가 이면 이를 i직원 ID로 설정합니다 empid. 그런 다음 awk에서 멋진 작은 트릭을 활용합니다. 표현식이 true로 평가되면 awk가 해당 행을 인쇄합니다. 따라서 는 첫 번째 키가 현재 행 ( 로 저장됨 )이고 두 번째 키가 현재 행( )의 첫 번째 필드인 a[i][$1]2차원 배열의 요소입니다 . 하나가 추가되므로 각 특정 필드가 처음 표시될 때만 표현식이 true가 됩니다 . 이것이 참인지 여부만 인쇄하므로 이 명령은 각 ID의 첫 번째 항목을 인쇄합니다.empidia[i][$1]++++a[i][$1]==1empid

이를 위해서는 GNU awk가 필요합니다.

관련 정보