awk - $1 열이 이전 $1 열과 같지 않으면 이전 행 전체를 인쇄합니다.

awk - $1 열이 이전 $1 열과 같지 않으면 이전 행 전체를 인쇄합니다.

첫 번째 열의 문자열이 이전 줄의 첫 번째 열에 있는 문자열과 다를 경우 이전 줄 전체를 인쇄하는 awk 프로그램을 Linux에서 작성하려고 합니다.

또 다른 접근 방식은 첫 번째 열이 동일할 때마다 일치하는 열의 마지막 행 전체를 인쇄하고 이전의 동일한 열을 삭제하는 것입니다.

나는 다음 코드를 사용했습니다.

awk 'BEGIN { FS=OFS=";" } $1==last{next} {last=$1} {print last}' test.txt

하지만 이전 행의 첫 번째 열만 인쇄하는 것 같아요. 이전 줄 전체를 인쇄하는 방법은 무엇입니까?

내 입력 파일은 test.txt다음과 같습니다.

818522;"Joey";
817399;"john";
817399;"CCE";
817399;"smith";
817399;"Ron";
817400;
817400;
817400;
818000;"ODC";
890021;
890021;
890021;"rachel";
890021;"monica"

원하는 출력:

818522;"Joey";
817399;"Ron";
817400;
818000;"ODC";
890021;"monica"

답변1

귀하의 설명이 출력과 일치하지 않아 약간 혼란 스럽습니다. 귀하의 설명에 따르면 예상되는 출력은 다음과 같습니다.

818522;"Joey";
817399;"Ron";
817400;
818000;"ODC";

890021마지막 줄이므로 어떤 줄도 인쇄하지 않으므로 첫 번째 필드는 다음 줄과 다르지 않습니다. 이것이 실제로 원하는 것이라면 다음과 같이 할 수 있습니다.

$ awk -F';' '{ 
                if($1!=last && prevLine){ print prevLine } 
                { last=$1; prevLine=$0 }
             }' file
818522;"Joey";
817399;"Ron";
817400;
818000;"ODC";

마지막 줄에도 예외를 추가하려면 다음을 시도해 보세요.

$ awk -F';' '{ 
              if($1!=last && prevLine){
                print prevLine; 
                lastPrinted=last
              } 
              {
                last=$1; 
                prevLine=$0
              }
             }
             END{ 
                if($1 != lastPrinted){ print }
             }' file 
818522;"Joey";
817399;"Ron";
817400;
818000;"ODC";
890021;"monica"

last아이디어는 매우 간단합니다. 첫 번째 필드가 정의된 변수와 다르면 prevLine(그래서 첫 번째 줄을 인쇄하지 않음) 이전 줄( prevLine)을 인쇄하고 이전 줄의 첫 번째 필드( last)를 변수에 저장합니다. lastPrinted.

그런 다음 모든 행에 대해 last첫 번째 필드와 prevLine현재 행을 설정합니다. 마지막으로 파일의 끝에 도달하면( END{}) 줄의 첫 번째 필드가 지난번에 인쇄한 첫 번째 필드( )와 다른 경우 해당 줄을 인쇄합니다 lastPrinted.

답변2

$ awk -F';' '$1 != l1 && l1 != "" { print l0 };
             {l1 = $1; l0 = $0};
             END {if ($1 != $l1) {print}}' test.txt 
818522;"Joey";
817399;"Ron";
817400;
818000;"ODC";
890021;"monica"

-F';'옵션은 awk의 입력 필드 구분 기호( FS)를 세미콜론으로 설정합니다. awk는 각 입력 라인을 자동으로 분할 FS하고 필드를 $1, $2, $3, ...., $n에 할당합니다.

변수 l1sum은 첫 번째 필드( )와 전체 행( )을 l0보유하는 데 사용됩니다 .$1$0

대부분의 경우 awk스크립트는 일련의 PATTERN { ACTION }규칙입니다. PATTERN이 true로 평가되면 ACTION이 실행됩니다. PATTERN은 true 또는 false로 평가되는 모든 항목(정규식 일치, 변수 비교, 계산 등)이 될 수 있습니다. ACTION은 임의의 awk 코드 문일 수 있습니다. 이러한 규칙은 각 입력 줄에 대해 반복됩니다. PATTERN 또는 ACTION은 선택 사항일 수 있습니다. PATTERN이 누락된 경우 true로 평가된 것으로 간주되어 ACTION이 항상 실행됩니다. ACTION이 누락된 경우 기본 동작은 print(즉, 현재 입력 줄 인쇄)입니다. 이는 매우 간단하고 단순화된 요약입니다. 자세한 내용은 awk 문서를 참조하세요(예: man awkGNU awk를 사용하는 경우 info awkO'Reilly도 참조).sed와 awkDale Dougherty와 Arnold Robbins의 책).

awk 스크립트의 첫 번째 줄은 현재 줄이 다음과 같은지 여부를 테스트합니다 $1.같지 않음둘 다l1 그리고빈 문자열. 두 테스트가 모두 true이면 마지막 입력 줄을 인쇄합니다 l0. 입력의 첫 번째 줄은 l1항상 비어 있으므로(스크립트의 두 번째 줄은 아직 실행되지 않았으므로 아직 값이 할당되지 않았기 때문에) 아무 것도 인쇄되지 않습니다( l0어차피 비어 있음) . , 따라서 인쇄하면 빈 줄만 출력됩니다.)

awk 스크립트의 두 번째 줄은 무조건 현재 입력 줄의 합계를 설정합니다 l1.l0

스크립트는 각 입력 줄에 대해 이 두 줄의 코드를 반복합니다.

더 이상 입력이 없으면 기본 스크립트 루프가 종료되고 END {...}블록이 실행됩니다. 현재 입력 줄(즉, 입력의 마지막 줄)을 인쇄합니다. 현재는 $1 != l1리플렉션(및 일부 간단한 테스트)을 사용하는 경우에만 해당 테스트 없이도 잘 작동할 수 있습니다 END {print}.

답변3

$ mlr --csv --fs ';' -N --ragged unsparsify then tail -n 1 -g 1 file
818522;Joey;
817399;Ron;
817400;;
818000;ODC;
890021;monica;

이는 다음을 사용합니다.밀러( mlr)는 데이터를 제목 없는 CSV로 읽고 ;필드 구분 기호 역할을 합니다. 입력을 통해 각 레코드는 서로 다른 수의 필드를 가질 수 있습니다.

먼저 이 작업을 사용하여 각 레코드의 존재하지 않는 필드를 null 값으로 채운 unsparsify다음 tail첫 번째 필드로 그룹화할 때 각 그룹의 마지막 값을 가져옵니다.

필요한 경우 출력에 인용문이 추가되거나 --quote-all모든 필드에 인용문을 추가할 수 있습니다.

답변4

사용 datamash:

$ datamash -t ';' -g 1 last 2 <file

-t ;필드 구분 기호로 세미콜론을 설정합니다.

last 2필드 2의 마지막 값을 인쇄합니다.

-g 1예의 약어입니다 groupby 1.

이 명령은 다음에서 가져온 것입니다.Datamash는 단 하나의 라이너를 대체합니다.. "각 그룹의 마지막 값"을 참조하십시오.

관련 정보