разделить таблицу матриц на основе соответствия ячеек столбцу

Для начала, конвейер сторожевого пса из вашего вопроса, вероятно, не убьет process1, если он снова не пытается писать на мертвую трубу. Поэтому ваш сторожевой пёс должен каким-то образом явно убить процесс1.

В дополнение к этому вот очень простой watchdog.sh сценарий оболочки. Вы можете проверить его в интерактивном режиме в консоли. Просто введите ./watchdog.sh. Он будет дублировать все, что вы вводите, и остановится, если вы ничего не введете в течение 5 секунд.

#!/bin/bash

# first arg is timeout (default: 5)
T="${1:-5}"
PID=$$

exec tee >(bash -c '
while true ; do
    bytes=$(timeout '$T' cat | wc -c)
    if ! [ "$bytes" -gt 0 ] ;then
            break
    fi
done
## add something like "killall process1", for now we just kill this tee command
kill -9 '$PID)

Заметьте, что скрипт на самом деле будет иметь таймаут между T и 2*T (иначе это было бы намного сложнее). Каким-то образом можно добавить способ убить process1, как я уже говорил.

Ниже пример для тестирования.

process1.sh:

#!/bin/bash

echo "here we are ..."
sleep 2
echo "still alive ..."
sleep 20
echo "too late ..."

И запустите его следующим образом (включая уродливый способ убить process1.sh по таймауту):

(./process1.sh & echo $! >/tmp/pid; wait) |(./watchdog.sh 5; kill `cat /tmp/pid`)
2
18.08.2017, 18:35
4 ответа

Самый простой способ, который я могу придумать, это сохранить первую строку как переменную, а затем распечатать остальные по мере необходимости. Это, однако, требует сохранения всего входного файла в памяти:

#!/bin/gawk -f
{
    if(NR==1){
        header[1]=$1;
        header[2]=$2;
        for(i=3;i<=NF;i++){
            header[$i]=i;
        }
    }
    else{
        data[$1][NR]=$2"\t"$(header[$1]);
    }
}
END{
    OFS="\t";
    for(i in data){
        print header[1],header[2],i > i".txt"
        for(k in data[i]){
            print i,data[i][k] >> i".txt"
        }
    }
}

Сохраните этот скрипт как foo.awk, сделайте его исполняемым ( chmod a+x foo.awk) и запустите это в вашем файле:

foo.awk file
0
27.01.2020, 22:03

Вы можете использовать awk:

awk 'NR>1{if ($1!=p){N="file"++C; print "Name\tID\t"$1 >N};
             print $1,$2,$(C+2)>N}{p=$1}' infile.txt
1
27.01.2020, 22:03

Полноерешение awk:

awk 'NR==1{ len=split($0,a_pos); for(i=1;i<=len;i++) a_keys[a_pos[i]]=i }
     NR>1{ if(!r[$1]++) { fn="file"++c; print "Name\tID\t"$1 > fn } 
           print $1,$2,$(a_keys[$1]) > fn 
     }' OFS='\t' file
  • len=split($0,a_pos)-разбивает 1-ю строку на массив "ключей" (массив a_posиндексируется целыми числами)

  • for(i=1;i<=len;i++) a_keys[a_pos[i]]=i-преобразование a_posв массив a_keys, который будет проиндексирован строковыми ключами (для дальнейшей обработки)

  • fn="file"++c-создание имени файла


Просмотр результатов:

for f in file[0-9]*; do (echo "$f"; cat "$f"; echo); done

Выход (file1, file2, file3и file4последовательно):

file1
Name    ID  ABC12
ABC12   123456  XX
ABC12   123456  XX

file2
Name    ID  ABCD12
ABCD12  123456  YY
ABCD12  123456  YY

file3
Name    ID  ABCD123
ABCD123 123456  ZZ
ABCD123 123456  ZZ

file4
Name    ID  ABCD1234
ABCD1234    123456  JJ
ABCD1234    123456  JJ
2
27.01.2020, 22:03

Использование:./split_matrix.awk input.txt

#!/usr/bin/awk -f

BEGIN {
    cnt = 1;
}

NR == 1 { 
    for(i = 3; i <= NF; i++) {
        headers[$i] = i;            
    }   
}
NR > 1 { 
    if( ! file_names[$1]) {
        file_names[$1] = cnt++;
        printf "%s %s %s\n", "Name", "ID", $1 > "file_"file_names[$1];
    }   
    printf "%s %s %s\n", $1, $2, $headers[$1] >> "file_"file_names[$1];
}

Тестирование

вход

Name    ID  ABC12   ABCD12  ABCD123 ABCD1234
ABC12   123456  XX  YY  ZZ  JJ
ABC12   123456  XX  YY  ZZ  JJ
ABCD12  123456  XX  YY  ZZ  JJ
ABCD12  123456  XX  YY  ZZ  JJ
ABCD123 123456  XX  YY  ZZ  JJ
ABCD123 123456  XX  YY  ZZ  JJ
ABCD1234    123456  XX  YY  ZZ  JJ
ABCD1234    123456  XX  YY  ZZ  JJ

вывод(используйте tail -n +1 -- file*для печати имени файла и содержимого файла. Я нашел этот трюк здесь)

==> file_1 <==
Name ID ABC12
ABC12 123456 XX
ABC12 123456 XX

==> file_2 <==
Name ID ABCD12
ABCD12 123456 YY
ABCD12 123456 YY

==> file_3 <==
Name ID ABCD123
ABCD123 123456 ZZ
ABCD123 123456 ZZ

==> file_4 <==
Name ID ABCD1234
ABCD1234 123456 JJ
ABCD1234 123456 JJ
0
27.01.2020, 22:03

Теги

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