이 문제에 대한 Perl 또는 awk 솔루션이 있습니까?

이 문제에 대한 Perl 또는 awk 솔루션이 있습니까?

입력 파일이 있습니다(입력.txt)다음과 같습니다.

id1      id2       name    weight 
53723848 12651711 timburnes 1.36667
53530214 12651711 timburnes 1.51191
53723848 53530214 timburnes 1.94
764157 52986038 ericcartman 0.861145
56797854 764157 ericcartman 1.35258
56797854 52986038 ericcartman 1.73781

알아채다첫 번째 줄은 실제 파일의 일부가 아니므로 명확성을 위해 여기에 추가합니다..

id1id2합계의 값을 두 개의 이름으로 추출하려고 합니다 .만.txt그리고반복.txt.

weight열 값이 1.5보다 크면중복된 신분증. 이 경우 id1값을 unique.txt파일로 이동하고 id2값을 duplicate.txt파일로 이동합니다.

가중치 열이 1.5보다 작으면 중복된 값이 없다는 뜻입니다. 따라서 이 경우에는 와 id1를 모두 id2이동 하겠습니다.만.txt문서.

따라서 위의 입력에 대해 출력은 다음과 같을 것으로 예상됩니다.

~을 위한만.txt문서,

53723848 timburnes
764157 ericcartman
56797854 ericcartman

~을 위한반복.txt문서,

12651711 timburnes
53530214 timburnes
52986038 ericcartman

아래 코드를 사용하여 중복 항목을 찾을 수 있습니다.

열 4를 기준으로 1.5보다 큰 값을 얻으려면

awk -F" " '$4 >= 1.5 { print $1" " $2" " $3" " $4}' file1.txt > Output.txt

이제 1.5보다 큰 값의 경우 아래 코드를 사용하여 이름을 기반으로 중복 ID를 병합할 수 있습니다.

  perl -ane 'foreach(@F[0..1]){$k{$F[2]}{$_}++}
           END{
                foreach $v (sort keys(%k)){
                    print "$_ " foreach(keys(%{$k{$v}})); 
                    print "$v\n"
                }; 
            } ' Output.txt

그러나 위의 방법으로는 원하는 방식으로 출력을 얻을 수 없습니다.

편집하다:

아래와 같이 입력에 대한 명령을 실행하고 있습니다.

awk '{
      if ($4 > 1.5) { 
          if (++dup[$2] == 1)  print $2, $3 > "duplicate.txt"
      } 
      else
          if (++uniq[$1] == 1) print $1, $3 > "unique.txt" 
}' << END
17412193 43979400 ericcartman 2.16667
21757330 54678379 andrewruss 0.55264
END 

내가 얻는 결과는,

-bash-3.2$ cat unique.txt
21757330 a.andreev
-bash-3.2$ cat duplicate.txt
43979400 ericcartman

그러나 내 예상 결과는 다음과 같습니다.

cat unique.txt
17412193 ericcartman
21757330 andrewruss
54678379 andrewruss
cat duplicate.txt
43979400 ericcartman

답변1

awk해결책 은 다음과 같습니다 .

$ awk '
    $4 < 1.5 {
      uniq[$1] = $3;
      uniq[$2] = $3;
      next;
  }
  {
      uniq[$1] = $3;
      dup[$2] = $3;
      delete uniq[$2];
  }
  END {
    print "--unique.txt--";
    for(i in uniq) {
        print i,uniq[i]
    }
    print "";
    print "--duplicate.txt--";
    for(i in dup) {
        print i,dup[i]
    }
    }' file
--unique.txt--
764157 ericcartman
56797854 ericcartman
53723848 timburnes

--duplicate.txt--
53530214 timburnes
52986038 ericcartman
12651711 timburnes

두 번째 예를 사용하면 다음과 같습니다.

$ awk '
    $4 < 1.5 {
      uniq[$1] = $3;
      uniq[$2] = $3;
      next;
  }
  {
      uniq[$1] = $3;
      dup[$2] = $3;
      delete uniq[$2];
  }
  END {
    print "--unique.txt--";
    for(i in uniq) {
        print i,uniq[i]
    }
    print "";
    print "--duplicate.txt--";
    for(i in dup) {
        print i,dup[i]
    }
    }' << END
> 17412193 43979400 ericcartman 2.16667
> 21757330 54678379 andrewruss 0.55264
END
--unique.txt--
21757330 andrewruss
54678379 andrewruss
17412193 ericcartman

--duplicate.txt--
43979400 ericcartman

답변2

$ awk '{
      if ($4 > 1.5) { 
          if (++dup[$2] == 1)  print $2, $3 > "duplicate.txt"
      } 
      else
          if (++uniq[$1] == 1) print $1, $3 > "unique.txt" 
}' << END
53723848 12651711 timburnes 1.36667
53530214 12651711 timburnes 1.51191
53723848 53530214 timburnes 1.94
764157 52986038 ericcartman 0.861145
56797854 764157 ericcartman 1.35258
56797854 52986038 ericcartman 1.73781
END

$ cat unique.txt 
53723848 timburnes
764157 ericcartman
56797854 ericcartman

$ cat duplicate.txt 
12651711 timburnes
53530214 timburnes
52986038 ericcartman

답변3

여기 Perl이 있습니다:

perl -lane '$F[3]>1.5 ? print STDERR "$F[1] $F[2]" : print STDOUT "$F[0] $F[2]"'\
 input.txt 2> duplicate.txt > unique.txt

여기서는 중복 항목을 확인하지 않습니다. 귀하의 질문을 올바르게 이해했다면 이미 그렇게 하신 것입니다. 중복 항목인지 여부는 마지막 필드의 값에 따라 달라집니다. 제가 잘못 이해한 부분이 있다면 알려주시면 업데이트하겠습니다.

위의 코드는

$ cat duplicate.txt 
12651711 timburnes
53530214 timburnes
52986038 ericcartman

$ cat unique.txt 
53723848 timburnes
764157 ericcartman
56797854 ericcartman

관련 정보