두 개의 입력 파일의 열을 포함하는 파일을 만들고 싶습니다.
파일 1은 다음과 같습니다.
11111111 abc12345 Y
22222222 xyz23456 Y
파일 2:
11111111 abc12345
33333333 kbc34567
출력은 다음과 같아야 합니다.
11111111 abc12345 Y
22222222 xyz23456 Y
33333333 kbc34567
다음을 시도하여 중복 항목을 찾을 수 있었지만 첫 번째 파일과 다른 레코드의 중복 항목도 동일한 형식(첫 번째, 두 번째 및 세 번째 열 사이의 동일한 공간)이어야 합니다.
awk 'FNR==NR{a[$1$2]=$1$2;next} ($1$2 in a) {print a[$1$2],$3}' file2 file1
답변1
i) 연결된 첫 번째 및 두 번째 필드와 ii) 세 번째 필드를 인쇄하고 있기 때문에 공백이 변경됩니다. 기본적으로 awk
공백은 출력 필드 구분 기호( )로 사용되므로 공백이 OFS
엉망이 됩니다. 간단한 해결책은 $0
행 자체( )를 필드 대신 배열에 저장하는 것입니다.
a[$1$2]=$0;
그러나 어쨌든 스크립트는 원하는 대로 작동하지 않습니다. file2에 있는 file1의 줄만 인쇄하므로 file1에만 있는 줄은 모두 건너뜁니다. 원하는 출력에 따라 두 파일의 모든 줄을 인쇄하고, file2의 한 줄에 file1의 처음 두 필드와 동일한 처음 두 필드가 있는 경우 file1의 해당 줄만 인쇄하려고 합니다. 다음과 같은 방법으로 이 작업을 수행할 수 있습니다 awk
.
awk 'FNR==NR{a[$1$2]=$0; print} !($1$2 in a) {print}' file1 file2
file1
그러면 배열의 각 행이 저장되고 인쇄됩니다. 그런 다음 file2
처리 시 처음 두 필드가 없는 모든 행을 인쇄합니다 a
.
다음을 사용하여 이 작업을 수행할 수도 있습니다 sort
.
$ sort -uk1,2 file1 file2
11111111 abc12345 Y
22222222 xyz23456 Y
33333333 kbc34567
두 파일 모두에서 공백의 양이 동일한지 확인하거나(예제에서는 그렇지 않음) 이를 달성하려면 다음 명령을 사용하면 됩니다.
$ sed 's/ */\t/g' file1 file2 | sort -uk1,2
11111111 abc12345 Y
22222222 xyz23456 Y
33333333 kbc34567
답변2
파일 크기에 따라 이것이 가장 효율적인 접근 방식이 아닐 수도 있지만 특정 상황에서는 작동한다고 생각합니다. 파일이 특정 순서로 되어 있을 필요는 없지만 항상 File2보다 File1을 선호해야 합니다.
#!/bin/bash
# Make a list of the unique identifiers in each of the files, changing the whitespace in between into a comma.
awk '{print $1 "," $2}' File1 File2| sort | uniq |
# Loop through all the unique identifiers we just found
while read l; do
# Create a regular expression for each identifier to use as
# a search term, changing the comma into "any number of whitespaces"
searchterm=$(echo $l | sed 's/,/\\\s*/')
# if this pattern exists in File1
if $(grep -E "$searchterm" File1 >& /dev/null); then
# print it out
grep -E "$searchterm" File1
else
# otherwise, print it if it's in File2
grep -E "$searchterm" File2
fi
done
File3을 원하면 스크립트로 저장하고 거기로 출력을 보낼 수 있습니다.
#copy to merge_uniq.sh
chmod +x merge_uniq.sh
merge_uniq.sh > File3
답변3
awk 'BEGIN{i=0} {if (!($1$2 in a)) {a[$1$2]=$0; index_array[i] =$1$2; i++} } END{for (j=0; j<i; j++) print a[index_array[j]]}' 1 2
11111111 abc12345 Y
22222222 xyz23456 Y
33333333 kbc34567