두 번째 "키-값" 파일의 해당 키에 매핑되지 않는 데이터 필드가 포함된 하나의 "키-값 목록" 파일에서 행을 찾습니다.

두 번째 "키-값" 파일의 해당 키에 매핑되지 않는 데이터 필드가 포함된 하나의 "키-값 목록" 파일에서 행을 찾습니다.

2개의 파일이 있습니다. 한 파일에는 한 줄에 최소 2개의 필드(사용자 이름, 연령 및 해당 필드의 다양한 "과일" 수)가 포함되어 있으며, 다른 파일에는 항상 한 줄에 두 개의 필드(사용자 이름 및 "과일")가 포함되어 있습니다. 나는 그것들을 file1"데이터베이스" 파일과 file2"매핑" 파일 이라고 부르겠습니다 .

file1각 사용자 이름에 대해 해당 사용자에 해당하는 행에 "fruit"가 포함되어 있는지 확인하고 싶습니다.아니요이 사용자에게 매핑되었습니다 file2.

예:

  • file1(이 파일의 한 줄당 과일 수는 가변적입니다.)

    james,25,strawberry,rassberry,blueberry
    james,25,strawberry,rassberry,mango
    james,26,blueberry
    james,27,pineapple
    erik,30,strawberry,rassberry,mango
    
  • file2:

    james,strawberry
    james,rassberry
    james,blueberry
    erik,blueberry
    erik,rassberry
    
  • 원하는 출력:

    james,25,strawberry,rassberry,mango
    james,27,pineapple
    erik,30,strawberry,rassberry,mango
    

    이 행은 사용자 또는 사용자와의 연결을 포함하지 않으며 file2사용자 또는 사용자와의 연결도 포함하지 않기 때문에 선택되었습니다.mangopineapplejamesstrawberrymangoerik

내 코드로는 부분적인 솔루션만 얻을 수 있습니다. 아래에서 시도했지만 같은 행의 다른 열은 확인하지 않습니다.

awk 'BEGIN{FS=OFS=","}NR==FNR{a[$1]=$2;next}
{if (a[$1] && (a[$1]!=$3)){print $0, a[$1]}}' file2 file1

답변1

awk -F, '
    !nxtfile{ join[$1]= (join[$1]==""?"": join[$1] FS) $2; next }
            { split(join[$1], tmp, ","); for(x in tmp) fruits[tmp[x]];
              for(i=3; i<=NF; i++) if(!($i in fruits)) { print; break }
            }
' file2 nxtfile=1 file1

첫 번째 블록에서는 입력을 처리하고 있습니다.파일 2동일한 결과를 얻으려면 다른 행의 모든 ​​과일을 함께 연결하십시오.이름그리고 이를 키/값 쌍으로 이름이 지정된 연관 배열에 저장합니다.가입하다.

두 번째 블록에서는 입력을 처리하고 있습니다.파일 1배열에서 첫 번째로 일치하는 필드의 값을 가져와서 쉼표 구분 기호를 사용하여 임시 배열로 분할합니다.tmp, 그런 다음 다른 배열을 재구성합니다.과일그리고 가치tmp키로 사용되는 배열과일배열(즉, 우리는tmp배열의 값은 다음과 같습니다.과일대량으로).

그런 다음 마지막 단계는 >=3 번째 필드를 끝까지 반복하고 해당 필드가 다음 위치에 있는지 하나씩 확인하는 것입니다.과일배열, 일치하지 않는 첫 번째 필드에서 전체 줄을 인쇄하고 나머지 필드를 계속 읽을 필요가 없으므로 루프를 중단합니다.

답변2

확실히 허용되는 awk 솔루션보다 더 많은 줄이 있지만 (나처럼) awk를 모르는 경우에는 더 명확할 수 있습니다.

이는 Python의 컬렉션을 사용하여 "이 과일 목록에 조회/참조 목록에 없는 요소(과일)가 있습니까?"라고 명시적으로 질문할 수 있습니다.

import csv
import sys
from collections import defaultdict

# Will look something like { james: [strawberry, ...], erik: [blue, ...] }
lookup = defaultdict(set)

with open('file2', newline='') as f:
    reader = csv.reader(f)

    for row in reader:
        name, fruit = row
        lookup[name].add(fruit)


writer = csv.writer(sys.stdout)

with open('file1', newline='') as f:
    reader = csv.reader(f)

    for row in reader:
        name = row[0]
        these_fruits = set([x for x in row[2:] if x])

        # see my note below on how set.difference(set) works
        if not these_fruits.difference(lookup[name]):
            # no difference
            continue

        writer.writerow(row)

작동 방식은 다음과 같습니다 set.difference(set).

>>> {1,2}.difference({1,2,3})
set()
>>> {1,2,3}.difference({1,2,3})
set()
>>> {1,2,4}.difference({1,2,3})
{4}

왼쪽에 요소가 있고 오른쪽에 요소가 없을 때까지는 차이가 없습니다.

관련 정보