UNIX에서 심층 검색 확장

UNIX에서 심층 검색 확장

내 파일에는 사용자와 감독자 관계가 있는 다음 데이터가 있습니다.

user |supervisor |id
-----|-----------|----
a    |   b       | 1
b    |   c       | 2
c    |   d       | 3
e    |   b       | 4

아래와 같이 사용자와 감독자 간의 관계 계층을 분석하고 싶습니다.

user |supervisor |id
-----|-----------|----
a    |   b       | 1
a    |   c       | 1
a    |   d       | 1
b    |   c       | 2
b    |   d       | 2  
c    |   d       | 3
e    |   b       | 4
e    |   c       | 4
e    |   d       | 4 

보시다시피, 사용자 "a"의 경우 직속 감독자는 "b"이지만 "b"는 다시 "c"를 그의 감독자로 갖습니다. 따라서 간접적으로 "c"는 "a"의 감독자이기도 합니다. 예를 들어, 내 목표는 특정 사용자에 대한 계층 구조의 모든 수준을 분석하는 것입니다. Unix에서 이 기능을 구현하는 가장 좋은 방법은 무엇입니까?

답변1

각 사용자는 입력 파일("사용자" 열)에 한 번만 나타난다고 가정합니다. 또한 파이프( |) 구분 기호가 실제로 파일에 있고 항상 공백으로 데이터와 구분되며 헤더 행은 다음과 같다고 가정합니다.아니요실제로 존재합니다.

이것이 사용된 2단계 솔루션입니다 awk. 첫 번째 단계에서는 각 사람의 감독자가 포함된 배열을 작성하고, 두 번째 단계에서는 출력을 작성합니다.

awk 'pass==1 { super[$1] = $3; }
     pass==2 {
                print
                user=$3
                while (super[user] != "") {
                        print $1, "|", super[user], "|", $5
                        user=super[user]
                }
             }
    ' pass=1 data pass=2 data

이렇게 하면 제대로 정렬되지 않은 출력이 생성됩니다. 이 문제를 해결하려면 파이프하세요 column -t. 또는 awk필요한 경우 스크립트에서 출력 형식을 지정할 수 있습니다 .

그런데 이 작업을 흔히전이적 폐쇄.

답변2

복잡한해결책:

awk 'NR<3{ h=(h=="")? $0 : h ORS $0 }NR>2{ uid[$1]=$5; us[$1]=$3 }
     END{ 
         print h; 
         for (u in uid) { 
             id=uid[u]; spvr=us[u]; printf("%-5s|%-11s|%-4s\n",u,spvr,id); 
             while (spvr in uid) { 
                 spvr=us[spvr]; printf("%-5s|%-11s|%-4s\n",u,spvr,id) 
             } 
         }
     }' yourfile

산출:

user |supervisor |id
-----|-----------|----
a    |b          |1   
a    |c          |1   
a    |d          |1   
b    |c          |2   
b    |d          |2   
c    |d          |3   
e    |b          |4   
e    |c          |4   
e    |d          |4 

세부 사항:

  • NR<3{ h=(h=="")? $0 : h ORS $0 }- 캡처머리글철사

  • uid[$1]=$5-사용자 ID관계형 배열

  • us[$1]=$3-사용자 감독자관계형 배열

  • spvr=us[u]- 1위가정 교사현재를 위해사용자

  • while (spvr in uid) { ... }- 하지만가정 교사에 있습니다사용자목록, 상위 가져오기가정 교사

답변3

내 awk 솔루션(RomanPerekhrest의 출력 형식 사용) 기본적으로 두 개의 관련 루프가 있습니다. 첫째, 사용자를 위한 새로운 감독자에 대해 작업하는 경우 해당 감독자의 모든 종속성(즉, 감독자 체인)이 해당 사용자에게 추가되어야 합니다. 그런 다음 두 번째 루프는 현재 처리된 사용자를 종속성으로 갖는 다른 모든 사용자를 찾아 현재 사용자의 모든 종속성을 여기에 추가합니다.

#!/usr/bin/awk
# file process_it.awk
BEGIN {

    FS="|";
}

NR<3 {

    h=(h==""? $0 : h ORS $0)
}

NR>2 {

   gsub(/ /, "", $0)
   curr_user=$1;
   curr_supervisor=$2;
   curr_id=$3;
   print curr_user, curr_supervisor;
   arr[curr_user][curr_supervisor]++;
   id[curr_user]=curr_id;

   if(isarray(arr[curr_supervisor])) {
       for(sub_indx in arr[curr_supervisor])
           arr[curr_user][sub_indx]++;
    }
    else
        delete arr[curr_supervisor];

    for(indx in arr) {

        if(isarray(arr[indx])) {

            for(sub_indx in arr[indx]) {

                if(sub_indx==curr_user) {

                    for(sub_indx2 in arr[curr_user])
                    arr[indx][sub_indx2]++;
                }
            }    
        }
    }
}

END {
    print h;

    for(i in arr) {

        if(isarray(arr[i])) {

            for(j in arr[i])
                printf "%-5s|%-11s|%-3s\n", i, j, id[i];
        }
    }
}

사용:

awk -f process_it.awk your_file.txt

관련 정보