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

У меня есть большая разделительная матрица в файле в Linux:

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 

Я хочу разбить эту матрицу на отдельные файлы на основе соответствия в 1-м столбце, [это большой файл, не может считать номера столбцов]

ожидаемый результат:

Файл 1;

 Name ID ABC12 ABC12 123456 XX ABC12 123456 XX 

Файл 2;

 Name ID ABCD12 ABCD12 123456 YY ABCD12 123456 YY 

Файл 3;

 Name ID ABCD123 ABCD123 123456 ZZ ABCD123 123456 ZZ 

Файл 4;

 Name ID ABCD1234 ABCD1234 123456 JJ ABCD1234 123456 JJ 

4 Solutions collect form web for “таблица разбиения на основе соответствия ячейки столбцу”

Полное решение 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 – flipping a_pos в массив a_keys который будет проиндексирован строковыми ключами (для дальнейшей обработки)

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


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

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

Вывод ( file1 , file4 и 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 

Вы можете использовать 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 

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

 #!/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 

Использование: ./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 

output (используйте 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 
  • Случайные аргументы (содержащие цветовые коды) из массива
  • Как запустить сценарий оболочки в качестве демон в Redhat?
  • Шаблон Regex для замены нескольких значений с помощью sed
  • Получение отдельных байтов из двоичного файла в переменную с bash
  • Bash: перемещать файлы определенного шаблона
  • Scripting для разделения одной строки CSV на несколько
  • Почему мой скрипт не выполняется на if.up
  • zsh: команда map для массива
  • Удаление многих файлов, кроме одного типа
  • Список каталогов, затем файлы - с одной командой?
  • Правильная конструкция JSON
  • Linux и Unix - лучшая ОС в мире.