![두 번째 "키-값" 파일의 해당 키에 매핑되지 않는 데이터 필드가 포함된 하나의 "키-값 목록" 파일에서 행을 찾습니다.](https://linux55.com/image/198499/%EB%91%90%20%EB%B2%88%EC%A7%B8%20%22%ED%82%A4-%EA%B0%92%22%20%ED%8C%8C%EC%9D%BC%EC%9D%98%20%ED%95%B4%EB%8B%B9%20%ED%82%A4%EC%97%90%20%EB%A7%A4%ED%95%91%EB%90%98%EC%A7%80%20%EC%95%8A%EB%8A%94%20%EB%8D%B0%EC%9D%B4%ED%84%B0%20%ED%95%84%EB%93%9C%EA%B0%80%20%ED%8F%AC%ED%95%A8%EB%90%9C%20%ED%95%98%EB%82%98%EC%9D%98%20%22%ED%82%A4-%EA%B0%92%20%EB%AA%A9%EB%A1%9D%22%20%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C%20%ED%96%89%EC%9D%84%20%EC%B0%BE%EC%8A%B5%EB%8B%88%EB%8B%A4..png)
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
사용자 또는 사용자와의 연결도 포함하지 않기 때문에 선택되었습니다.mango
pineapple
james
strawberry
mango
erik
내 코드로는 부분적인 솔루션만 얻을 수 있습니다. 아래에서 시도했지만 같은 행의 다른 열은 확인하지 않습니다.
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}
왼쪽에 요소가 있고 오른쪽에 요소가 없을 때까지는 차이가 없습니다.