Нужен сценарий 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 

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

  • Запись файлов grep за последние 30 минут
  • Сделать awk и получить столбцы
  • AWK: разделитель полей
  • Скользящее среднее в файле журнала с awk или другими утилитами unix?
  • Awk для удаления строки, если аргумент встречается в определенном столбце
  • Распечатайте количество значений, в которых есть специальные символы
  • Как сделать следующее форматирование с помощью сценария sed или awk или bash на linux
  • Как отформатировать число с плавающей запятой с точностью до 2 значащих цифр в bash?
  • 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 - лучшая ОС в мире.