열을 기준으로 두 파일을 비교하고 인쇄합니다.

열을 기준으로 두 파일을 비교하고 인쇄합니다.

400,000줄의 큰 파일 두 개가 있습니다. 두 번째 파일의 열 1과 첫 번째 파일의 열 1을 재귀적으로 비교하고 싶습니다. 일치하면 전체 줄을 인쇄하고 싶습니다. 정렬된 파일입니다.

file 1:
  name   values
  aaa    10
  aab    acc
  aac    30
  aac    abc

file2:
  aaa
  aac
  aac
  aad

파일에 400,000줄이 포함되어 있으므로 처리하는 데 시간이 걸립니다.

내 현재 솔루션은 다음과 같습니다

#!/bin/ksh
while read line
do
var=`echo $line `
grep "$var" file1 >> /dev/null
if [ $? -eq 0 ]
then
grep "$var" file1 >> present
else
echo " $line missing " > missing
fi
done < "file2"

여기에서 사용하는 것 때문에 grep값이 예상한 열 1이 아닌 파일 1의 어딘가에 나타날 수 있으며 그런 일이 발생하지 않기를 바랍니다.

내 예상 솔루션:

  1. 두 번째 파일만 첫 번째 파일의 열 1과 비교합니다(이렇게 해도 시간이 오래 걸립니다).
  2. 파일 포인터가 있는 스크립트를 사용하여 perl파일의 두 열을 비교합니다. 문자열이 일치하면 인쇄하십시오. 그렇지 않고 첫 번째 파일의 열 1이 두 번째 파일의 열보다 크면 파일 2가 증가되어 비교됩니다. 반대의 경우 파일 1의 열 1을 증가시키고 비교합니다.

답변1

join file1 file2

기본적으로 각 파일에 대해 열 1을 사용하고 그 중 누락된 행을 무시합니다. 이는 원하는 것입니다. 또한 파일을 정렬해야 하는데 이는 이미 그렇습니다.

답변2

수량이라면고유한의 요소가 file2너무 크지 않은 경우 실행 가능한 솔루션은 두 개의 파일을 처리하는 고전적인 접근 방식을 사용하여 awk먼저 열 1에 있는 유일한 요소의 배열을 만든 file2다음 file1열 1이 배열의 구성원인지 테스트하는 것입니다. 지금

awk 'FNR==NR {a[$1]++}; FNR!=NR && a[$1]' file2 file1

연관 배열을 사용하는 동등한 접근 방식 bash 4+은 다음과 같습니다.

#!/bin/bash

declare -A a

while read col1 _ ; do
  ((a[$col1]++))
done < file2

while IFS= read -r line; do
  # compare only with 1st column of second file
  read -r col1 _ <<< "$line"
  [[ -n "${a[$col1]}" ]] && printf "$line\n"
done < file1

답변3

이것이 당신이 찾고 있는 것입니까? 나는 cut목록을 각각 하나의 열을 포함하는 배열로 분할하는 데 익숙합니다. 이는 열이 탭으로 구분되어 있다고 가정합니다. options 를 지정하여 구분 기호 자르기 사용을 변경할 수 있습니다 -d. 밑줄로 분할: cut -d '_'.

    #!/bin/bash

    FILE1='somefile'
    FILE2='someotherfile'

    # File 1, column 1
    f1c1=($(cut -f1 -s $FILE1))
    # File 1, column 2
    #f1c2=($(cut -f2 -s $FILE1))

    # File 2, column 1
    f2c1=($(cut -f1 -s $FILE2))
    # File 2, column 2
    #f2c2=($(cut -f2 -s $FILE2))

    # Looping through all items in file 1 column 1
    for x in "${f1c1[@]}"
    do
        # For each item in f1c1, check all items in f2c1 for a match
        for y in "${f2c1[@]}"
        do
            if [[ $x == $y ]]
            then
                # The items matched!
                echo $x
                # Breaking out of the loop (no need to check for more than one
                # match, right?)
                break
            fi
        done
    done

관련 정보