다음과 같이 샘플 데이터 파일을 업데이트합니다.
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인지(즉, 속성이 아직 발견되지 않았는지) 확인하고,print
true인 경우(부정 연산자 덕분에) 작업을 수행하고 카운터를 증가시킵니다.그 다음에(이는 C 스타일 프로그래밍 언어에서 접두사/접미사 증가가 작동하는 방식과 동일합니다.) 따라서 해당 속성이 아직 발견되지 않은 경우 인쇄되지만 이후 발생은 무시됩니다.
노트이 delete a
명령문은 2012 POSIX 표준에서 허용하는 구문을 따르고 위의 내용은 GNU 및 GNU에 적용되지만 awk
Stéphane Chazelas mawk
는 nawk
이 구문을 지원하지 않는 구현에 대해 다음과 같이 언급했습니다.
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의 첫 번째 항목을 인쇄합니다.empid
i
a[i][$1]
++
++a[i][$1]==1
empid
이를 위해서는 GNU awk가 필요합니다.