특정 열에서만 두 파일을 행별로 비교합니다.

특정 열에서만 두 파일을 행별로 비교합니다.

if i in [2,4,7]awk의 for 루프 구문은 무엇입니까? 또한 아래 코드에서 이를 구현하는 방법을 알아보세요. 감사해요

입력하다:

$ cat f1
col1,col2,col3,col4,col5,col6,col7
col11,col12,col13,col14,col15,col16,col17
$ cat f2
col1,col2,col03,col4,col5,col06,col7
col11,col12,col13,col14,col015,col16,col17

$   awk -F,  '
   NR==FNR {
     a[FNR][0]=$0        #populate base file records
     for(i=1;i<=NF;i++)
       a[FNR][i]=$i      #populate base file fields
         next
   }
   {
     for(i=1;i<=NF;i++)
       {
       #if(i in [2,4,7])  <***How to chieve this column in list of values*** >
         #continue;
       if($i!=a[FNR][i])
         {
         printf "Line#%d, column:%d is different in two files.\n",FNR,i
         # ***<TODO print record from first file and second file after printing all mismatch columns>***
         }
       }
   }' f1 f2

예상 출력:

Line#1, column:3 is different in two files.
Line#1, column:6 is different in two files.
col1,col2,col3,col4,col5,col6,col7
col1,col2,col03,col4,col5,col06,col7>
Line#2, column:5 is different in two files.
col11,col12,col13,col14,col15,col16,col17
col11,col12,col13,col14,col015,col16,col17>

답변1

기본적으로 두 파일을 행별로 비교하고 특정 열을 제외하면 GNU를 사용하여 단어 awk경계를 지원할 수 있습니다 \<.\>

awk -F, -v skip='2,4,7' 'BEGIN{ filetwo=ARGV[1]; ARGV[1]=""; };{
    getline lf2 <filetwo; split(lf2, arr, ",");
    for (i=1; i<=NF; i++) {
        if ( (skip !~ "\\<"i"\\>") && $i!=arr[i] ) {
            print "Line#"FNR, "Column#" i " is different in two files."; mismatch=1; };
    };
}; mismatch { print $0; print lf2; mismatch=0; };' file2 file1

또는 모든 awk버전:

awk -F, -v skip_cols='2,4,7' '
    BEGIN{ filetwo=ARGV[1]; ARGV[1]=""; split(skip_cols, skip, ","); };{
    getline lf2 <filetwo; split(lf2, arr, ",");
    for (i=1; i<=NF; i++) {
        if ( !(i in skip) && $i!=arr[i] ) {
            print "Line#"FNR, "Column#" i " is different in two files."; mismatch=1; };
    };
}; mismatch { print $0; print lf2; mismatch=0; };' file2 file1

코드를 설명하세요.

  • 이것BEGIN { ... }막힌: 이는
    입력을 읽기 전에 먼저 수행됩니다.awk

    • ARGV 사용, filetwo=ARGV[1];:
      명령에 전달된 두 번째 인수(예: file2)를 읽고 이를 filetwo변수 에 저장 ARGV[0]합니다 .그 자체, 세 번째 ARGV[2]는 입니다 file1.
    • 매개변수 값을 읽은 후 해당 값을 설정 해제하므로 awk는 읽을 매개변수를 ARGV[1]=""찾지 못합니다 ().file2
    • skip="2 4 7";:
      우리는바꾸다(바라보다할당 표현식) skip무시하려는 열 번호를 설정합니다.
  • getline주문하다- 바라보다getline파일의 변수 사용:
    file2에서 한 줄을 읽고 이를 변수에 할당합니다 lf2(이제 위의 변수에는 filetwo우리가 읽은 두 번째 인수의 이름이 포함되어 있습니다 ARGV[1]).

  • split()기능:
    읽기 라인을 분할합니다파일 2이는 lf2쉼표 문자의 변수 에 있으며 이름이 지정된 배열에 저장됩니다. 이제 행의 각 필드 ,는 (첫 번째 필드), (두 번째 필드), (세 번째) 등으로 주소가 arr.지정됩니다 .arr[1]arr[2]arr[3]

  • 이내에for-loop성명우리는 다음 두 가지를 확인합니다.

    • 열 번호를 나타내는 변수 값은 변수 값에 표시되지 않습니다 i(; 그리고 GNU 특정 단어 경계 앵커이므로 일치하지 않습니다).! ~skipskip !~ "\\<"i"\\>"\<\>awki=222
    • file1의 컬럼 값이 동일한 인덱스를 가진 file2의 동일한 컬럼과 동일한지 확인합니다. $i!=arr[i]; 동일하지 않으면 일치하지 않는 행 번호 FNR와 차이 컬럼 인덱스를 인쇄 i하고 제어 변수를 설정합니다 mismatch=1.
  • mismatch { print ... }lf2: 불일치가 감지되고 명령문에 변수가 설정되고 다음 줄의 변수가 재설정 되는 경우에만 mismatchfile1의 두 줄을 인쇄한 다음 file2의 줄을 인쇄합니다 .ifmismatch=0

답변2

내가 올바르게 이해했다면:

  • 모든 필드에 대해 for 루프를 수행하려고 합니다. for(i=1;i<=NF;i++) { ... }
  • 내부: i가 4개 값 중 하나일 때 건너뛰고 싶습니다. (awk에서 "계속"은 현재 for 루프의 나머지 부분을 우회하고 다음 반복으로 이동합니다.

쉬운 방법: 필드를 건너뛰려면 다음 기술을 사용하면 됩니다.

BEGIN { skip[2]++; skip[3]++; skip[22]++; skip[23]++ }

....
 for(i=1;i<=NF;i++) {
   if (i in skip) { continue ; rem="Will skip for values defined in skip array indexes" }
   ...

BEGIN 섹션에서 "skip"을 정의하는 대신 건너뛸 인덱스가 4개(한 줄에 1개) 있는 파일이 있고 NR==FNR 조건을 사용하여 파일을 읽고 이 Skip the array로 채울 수도 있습니다. NR!=FNR인 경우(소스 파일을 읽을 때) 위 방법을 사용하여 필드를 건너뛸 수 있습니다.

답변3

$ cat tst.awk
BEGIN {
    FS=","
    split("2,4,7",tmp)
    for (i in tmp) {
        skipFldNrs[tmp[i]]
    }
}
NR==FNR {
    old[FNR] = $0
    next
}
FNR == 1 {
    for (fldNr=1; fldNr<=NF; fldNr++) {
        if ( !(fldNr in skipFldNrs) ) {
            chkFldNrs[++numToChk] = fldNr
        }
    }
}
old[FNR] != $0 {
    split(old[FNR],o)
    for (i=1; i<=numToChk; i++) {
        fldNr = chkFldNrs[i]
        if ( o[fldNr] != $fldNr ) {
            printf "Line#%d, column:%d is different in two files (\"%s\" vs \"%s\").\n", FNR, fldNr, o[fldNr], $fldNr
        }
    }
}

$ awk  -f tst.awk f1 f2
Line#1, column:3 is different in two files ("col3" vs "col03").
Line#1, column:6 is different in two files ("col6" vs "col06").
Line#2, column:5 is different in two files ("col15" vs "col015").

관련 정보