простая таблица транспонирования скриптов

простая таблица транспонирования скриптов

Я пытаюсь написать скрипт, который просто транспонирует таблицу CSV. У меня есть файл:

head1;head2;head3
field11;field12;field13
field21;field22;field23

(и т. д.), и я хочу

head1;field11;field21
head2;field12;field22
head3;field13;field23

Я даже не имею ни малейшего представления о том, как это можно сделать. Я не прошу вас писать скрипт, мне нужна идея о том, как это сделать в стандартной оболочке (к сожалению, я не могу использовать bashism или расширения GNU, только POSIX)

ps. На самом деле, я могу это сделать, но только некрасивым и неэффективным способом. Я верю, что есть более красивый способ.

решение1

Транспонирование данных

head1;head2;head3
field11;field12;field13
field21;field22;field23
field31;field32;field33

можно сделать с помощью GNU datamash:

$ datamash -t ';' transpose <file
head1;field11;field21;field31
head2;field12;field22;field32
head3;field13;field23;field33

решение2

Вот краткая адаптациярешение bashкэтот похожий вопрос SOдля конкретных разделителей, которые у вас есть (точки с запятой):

declare -a array=( )                      # we build a 1-D-array

IFS=';' read -a line < "$1"                       # read the headline

COLS=${#line[@]}                          # save number of columns

index=0
while IFS=';' read -a line ; do
    for (( COUNTER=0; COUNTER<${#line[@]}; COUNTER++ )); do
        array[$index]=${line[$COUNTER]}
        ((index++))
    done
done < "$1"

for (( ROW = 0; ROW < COLS; ROW++ )); do
  printf "%s" ${array[$ROW]}
  for (( COUNTER = ROW+COLS; COUNTER < ${#array[@]}; COUNTER += COLS )); do
    printf ";%s" ${array[$COUNTER]}
  done
  printf "\n" 
done

решение3

Ваши данные разделены точкой с запятой (не CSV). Поэтому вы можете попробовать этот код:

awk -F';' '{OFS=";"}{ for (i=1; i<=NF; i++) a[i]= (i in a?a[i] OFS :"") $i; } 
    END{ for (i=1; i<=NF; i++) print a[i] }' input.txt

head1;field11;field21;field31
head2;field12;field22;field32
head3;field13;field23;field33

решение4

flds=3; for((i=1;i<=flds;i++));do
  printf '%s' "$(cut -d';' -f$i file)" |tr '\n' ';';echo
done

Связанный контент