Explode Depth Search в 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?

0
17.07.2017, 17:54
3 ответа

Я предполагаю, что каждый пользователь во входном файле (в столбце «Пользователь» )только один раз. Далее я предполагаю, что вертикальная черта(|)разделяет на самом деле находятся в файле, и что они всегда отделяются от данных пробелом, и что строка заголовка не на самом деле присутствует.

Вот двухпроходное -решение с использованием 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; если вы этого хотите, укажите нужные правила форматирования.

Между прочим, эта операция широко известна как транзитивное замыкание .

0
28.01.2020, 04:43

Комплексawkраствор:

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-пользователь -идентификатормассив отношений

  • us[$1]=$3-пользователь -руководительмассив отношений

  • spvr=us[u]-1-й руководитель для текущего пользователя

  • while (spvr in uid) {... }-пока супервизор находится в спискепользователей , получить родительский супервизор

0
28.01.2020, 04:43

Мое awk-решение (с использованием выходных форматов от Романа Перехреста ). По сути, есть две соответствующие петли. Во-первых, если для пользователя обрабатывается новый супервизор, то пользователю должны быть добавлены все зависимости этого супервизора (, т.е. цепочки супервизора -). После этого второй цикл ищет всех остальных пользователей, у которых в качестве зависимости есть текущий обрабатываемый пользователь, и к ним добавляются все зависимости текущего пользователя.:

#!/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
0
28.01.2020, 04:43

Теги

Похожие вопросы