서로 다른 파일 간의 열 비교

서로 다른 파일 간의 열 비교

여러 개의 파일(행 30000개와 열 32개로 구성된 약 20개 파일)이 있는데 동일한 문자열로 시작하는 행만 유지해야 합니다. 나는 이러한 사례가 내가 필요로 하는 것과 매우 유사하다는 것을 알았지만 어떻게 적용해야 할지 모르겠습니다.

두 개의 서로 다른 열을 사용하여 여러 파일(2개 이상)을 비교합니다.

두 개의 서로 다른 파일에 있는 두 열의 값을 비교하고 차이의 절대값이 작은 최대값보다 작은 전체 행을 에코하는 방법은 무엇입니까?

내 경우에는 각 파일의 첫 번째 열이 12자의 문자열로 구성되어 있는데, 모든 파일에 존재하는 문자열로 시작하는 줄만 유지하면 된다. (입력 파일당 하나의 파일 또는 위의 경우와 같이 하나의 출력 파일도 작동합니다). 내 파일은 다음과 같습니다.

파일 1:

 -13  -5   0 19.3769 46.9197   1
 -13  -4  -2 347.911 57.7232   1
 -13  -4  -1 38.5696 39.0027   1
 -13  -4   0 2227.39 124.894   1
 -13  -3  -3 113.001 40.2117   1
 -13  -3  -2 850.847 78.2881   1

파일 2:

 -13  -5   0 2.19085 50.4632   1
 -13  -4  -2 283.628 56.7731   1
 -13  -4  -1  41.179 48.6423   1
 -13  -4   0 1753.54  125.88   1
 -13  -3  -3 28.2363 40.6518   1
 -13  -3  -2 562.736 66.0301   1
 -13  -3  -1 750.747 77.2795   1

산출파일 1:

 -13  -5   0 19.3769 46.9197   1
 -13  -4  -2 347.911 57.7232   1
 -13  -4  -1 38.5696 39.0027   1
 -13  -3  -3 113.001 40.2117   1
 -13  -3  -2 850.847 78.2881   1

산출파일 2

 -13  -5   0 2.19085 50.4632   1
 -13  -4  -2 283.628 56.7731   1
 -13  -4  -1  41.179 48.6423   1
 -13  -3  -3 28.2363 40.6518   1
 -13  -3  -2 562.736 66.0301   1

답변1

한 가지 접근 방식은 먼저 여러 파일에 있는 12개의 초기 문자 집합을 모두 찾는 것입니다.

cut -c-12 file* | sort | uniq -c

위의 명령은 cut이름이 로 시작하는 각 파일의 처음 12자를 인쇄한 다음 file문자를 정렬하고 각 줄에서 찾은 횟수를 추가합니다 uniq -c. 샘플 파일에서 이 명령을 실행하면 다음이 반환됩니다.

$ cut -c-12 file* | sort | uniq -c
      1  -13  -3  -1
      2  -13  -3  -2
      2  -13  -3  -3
      2  -13  -4   0
      2  -13  -4  -1
      2  -13  -4  -2
      2  -13  -5   0

따라서 첫 번째 줄을 제외한 모든 줄이 두 파일에 모두 나타납니다. 이제 필요한 횟수(귀하의 경우 20회)만큼 발생하는 행만 유지하세요.

cut -c-12 file* | sort | uniq -c | rev | sed -n 's/ 20 *$//p' | rev

rev거꾸로 인쇄하면 됩니다. 여기서는 각 행의 마지막 필드가 표시된 횟수를 계산하는 데 사용하고 있습니다. 그런 다음 이를 전달 sed하고 공백, 20 및 0 이상의 공백으로 끝나는 줄만 인쇄하도록 지시합니다. 이렇게 하면 20번 나타나는 줄만 유지되고 마침내 rev원래 형식으로 돌아갑니다.

이제 grep검색할 문자열 목록으로 전체 콘텐츠를 전달할 수 있습니다.

$ grep -f <(cut -c-12 file* | sort | uniq -c | 
            rev | sed -n 's/ 20 *$//p' | rev) file*
 -13  -5   0 19.3769 46.9197   1
 -13  -4  -2 347.911 57.7232   1
 -13  -4  -1 38.5696 39.0027   1
 -13  -4   0 2227.39 124.894   1
 -13  -3  -3 113.001 40.2117   1
 -13  -3  -2 850.847 78.2881   1

쉘이 해당 <()형식을 지원하지 않는 경우 결과를 cut별도의 파일에 저장하여 사용하거나 루프에서 실행할 수 있습니다.

cut -c-12 file* | sort | uniq -d | 
    while IFS= read -r l; do grep -- "^$l" file1; done

각 파일의 출력을 별도의 파일에 넣으려면 다음을 사용하십시오.

cut -c-12 file* | sort | uniq -c | rev | sed -n 's/ 20 *$//p' | rev > list
for f in file*; do grep -f list "$f" > "$f.new"; done

관련 정보