Нужен сценарий Awk или Unix для транспонирования / поворота в следующем шаблоне

Файл содержит данные в следующем формате (первая строка – это заголовок):

N ; A ; B ========= 1 ; 01;02 2; 02;02 

Основываясь на первом столбце, я ожидаю следующий вывод: столбец N остается тем же, однако другие могут расти, это могут быть C, D, E и т. Д., И соответствующие значения могут быть захвачены.

 1;A;01 2;A;02 1:B;02 2;B;02 

Как я могу это сделать?

  • Удалите строки на основе шаблона, но сохраняя первые n строк, которые соответствуют
  • Объединение / объединение 2 текстовых файлов в соответствии с числовым полем
  • Печатать строки файла между двумя шаблонами соответствия
  • Извлечение значений из блока данных
  • Согласование шаблонов по нескольким строкам
  • Объединение столбцов в файл с помощью Awk
  • Ошибка в простом скрипте bash - mv + awk
  • Выравнивание шаблона и удаление всей строки
  • 3 Solutions collect form web for “Нужен сценарий Awk или Unix для транспонирования / поворота в следующем шаблоне”

    Вот фрагмент кода с использованием Python …

    Код:

     # read in the data with open('data_file', 'rU') as f: # read in the header header = [x.strip() for x in f.readline().split(';')] # drop the ====== dump_marker = f.readline() # get the rest of the data data = [[x.strip() for x in line.split(';')] for line in f.readlines()] # print the data in new format for i, col in enumerate(header[1:]): for line in data: print("{};{};{}".format(line[0], col, line[i+1])) 

    файл данных:

     N ; A ; B ========= 1 ; 01;02 2 ; 02;02 

    Результат:

     1;A;01 2;A;02 1;B;02 2;B;02 

    В bash это можно сделать с помощью внутренних команд, tail и cut :

     #! /bin/bash # Get header line header=$( head -n 1 data_file ) # Make a variable with all delimiters (2) delimiters=${header//[^;]/} # Make an array with all column names declare -a colnames=( ${header//;/ } ) # For all columns one at the time... for C in $(seq 2 $((${#delimiters}+1)) ) ; do index=$((C-1)) # Skip first 3 lines of data_file tail --lines=+3 data_file | cut -d\; -f1,$C | while read; do # Replace first ';' with column name line=${REPLY/;/;${colnames[$index]};} # Remove all spaces and print echo ${line// /} done done 

    Объяснение:

    Получить первую строку файла в переменной (которая затем может быть изменена)

     header=$( head -n 1 data_file ) 

    Удалите все символы из переменной, ожидающей разделитель cemi-colon

     delimiters=${header//[^;]/} 

    Теперь переменные $ delimiters содержат ';;'

    Заменить все ';' с пробелами. Это даст «НАБ». Одним или несколькими пробелами является разделитель массива:

     declare -a colnames=( ${header//;/ } ) 

    Получить количество символов в переменной:

     ${#delimiters} 

    Добавить один:

     $((${#delimiters}+1)) 

    затем

     $(seq 2 $((${#delimiters}+1)) ) 

    равно:

     $(seq 2 3 ) 

    Индекс в переменной переходит от 0..n, затем -1 для поиска имен столбцов:

     index=$((C-1)) 

    Прочитайте файл, пропустите первые 3 строки, покажите только номер столбца $C , прочитайте строку в переменной $REPLY :

     tail --lines=+3 data_file | cut -d\; -f1,$C | while read; do 

    И решение с использованием awk :

     awk -F';' '{ gsub(/ /,"");} NR==1 { cols = split($0, col); } NR > 2 { for (i = 2; i <= cols; i++) { data[col[i]";"$1] = $1";"col[i]";"$i; } } END { no = asorti(data, sorted); for (i = 1; i <= no; i++) { print data[sorted[i]]; } }' input 
    Linux и Unix - лучшая ОС в мире.