Как перенести n-ю строку в столбец?

Использованиеcsvkit:

Предположим, что входной файл похож на

a       10,000  e       u
a       o       e       u
a       o       "hello  world"  u
a       o       e       u

где все поля разделены табуляцией -и где также есть табуляция в -между helloи world(, даже если два слова принадлежат одному и тому же полю, как указано в кавычках ).

$ csvformat -t file.txt
a,"10,000",e,u
a,o,e,u
a,o,hello       world,u
a,o,e,u

Опция -tдля csvformatсообщает утилите, что ввод разделен табуляцией -.

Обратите внимание, что 10,000правильно процитирован, а кавычки вокруг helloworldудалены, так как теперь это недвусмысленно.

Для принудительного заключения всех полей в кавычки:

$ csvformat -t -U 1 file.txt
"a","10,000","e","u"
"a","o","e","u"
"a","o","hello  world","u"
"a","o","e","u"

Если ввод использует другой символ кавычек, как в

$ cat file.txt
a       10,000  e       u
a       o       e       u
a       o       'quote: "hello  world"' u
a       o       e       u

затем сделай это:

$ csvformat -t -q "'" file.txt
a,"10,000",e,u
a,o,e,u
a,o,"quote: ""hello     world""",u
a,o,e,u

Мы указываем, что во входных данных используется одинарная кавычка с -q "'".


Чтобы запустить это на нескольких файлах, преобразовав каждый из вкладки -с разделителями в CSV, предполагая, что мы хотим обработать все .txtфайлы в текущем каталоге:

for name in./*.txt; do
    csvformat -t "$name" >"${name%.txt}.csv"
done

Бит ${name%.txt}.csvудаляет расширение .txtиз имени файла и вместо этого добавляет расширение .csv. Это также можно записать как

for name in./*.txt; do
    csvformat -t "$name" >"./$( basename "$name".txt ).csv"
done

После этого у вас будет набор (нетронутых исходных).txtфайлов вместе с соответствующими .csvфайлами.

1
01.10.2019, 21:41
3 ответа

Вы можете автоматизировать и обобщить обработку входного файла, чтобы разрешить любые имена атрибутов и любое количество имен атрибутов, а не только девять, показанные в OP:

   "subject code"
   "date of birth"
   "favorite activities"
   "height (m)"
   "weight (lbs)"
   "test score + standard deviation"
   "color blind"
   "number of siblings"
   "average score"

Один из способов сделать это с помощью awk:

awk -v i=0 -v nAtt=9 '
    /table columns are:/ {i+=1;ii=nAtt*(i-1);next} 
    !/(^$|^[0-9]+ +([0-9]+\.*[0-9]+ +)*.+)/ {ii+=1;a[ii]=$0}
    /^[0-9]+ +([0-9]+\.*[0-9]+ +)*.+/ 
        {printf "\n%s\n", $(nAtt+1);
        c=0; 
        for(ii-=nAtt;ii++<1+(nAtt-1)*i;) {c++;printf "%-34s%s\n",a[ii],$c}}
                    ' file.txt

Пояснение:

  • в этом awk one -вкладыше есть три раздела, все они начинаются с сопоставления с образцом, как /.../, или против сопоставления -, как!/.../
  • но сначала при вызове awkя передаю в него две внешние переменные с опцией -v:i=0и nAtt=9. iпредставляет собой ранг блока данных (, т. е. порядковый номер блока атрибутов во входном файле :file.txt), а nAtt— количество атрибутов, которое в этом решении должно быть одинаковым для всех данных. блокировать.
  • 1-е сопоставление с шаблоном :каждый раз, когда awkвидит шаблон table columns are:, он понимает, что новый блок данных начинается со следующей записи, устанавливает два счетчика iи iiи переходит к следующему записывать.
  • 2-е сопоставление с шаблоном :, если считываемая запись не является ни пустой строкой, ни строкой, которая может соответствовать чему-то вроде :56 6.18 1307 5.73 167 0.564 2 3 1.7 subject_8293748/label/NMA.label, затем увеличивайте счетчик массива aiiи начинайте заполнять массив строками имен атрибутов, пока не достигнете...
  • 3-е сопоставление с шаблоном :если запись соответствует 56 6.18 1307 5.73 167 0.564 2 3 1.7, за которой следует любое количество символов, напечатать (nAtt+1)-е поле в этой записи, затем напечатать nAttимена и значения атрибутов, по одному в каждой строке, таким образом, чтобы имена атрибутов выравнивались по левому краю и усекались, если их длина превышала 34 символа.

Как упоминалось ранее:

  • Это будет работать для любого количества атрибутов (nAtt )в блоке атрибутов и для имен атрибутов, которые (или не различаются )от блока к блоку.
  • не -постоянное количество атрибутов в блоке возможно (и легко ), с небольшими изменениями сценария.
  • внешние переменные могут быть переданы в awk, например, с помощью:

    awk -v i=$i -v nAtt=$nAtt '...'

0
28.04.2021, 23:28

Насколько статичны ваши данные? Это обман?

awk '/^[0-9]/ {print $10 "\nsubject code\t\t\t" $1 "\ndate of birth\t\t\t" $2"\nfavorite activities\t\t" $3 "\nheight (m)\t\t\t" $4 "\nweight (lbs)\t\t\t" $5 "\ntest score + standard deviation\t" $6 "\ncolor blind\t\t\t" $7 "\nnumber of siblings\t\t" $8 "\naverage score\t\t\t" $9}' data.txt
1
28.04.2021, 23:28

Вот один из способов

awk 'BEGIN {
       a[1]="subject code"
       a[2]="date of birth"
       a[3]="favorite activities"
       a[4]="height (m)"
       a[5]="weight (lbs)"
       a[6]="test score + standard deviation"
       a[7]="color blind"
       a[8]="number of siblings"
       a[9]="average score"
     } {
       print $10
       for(c=0;c++<9;) {
         printf "%-34s%s\n",a[c],$c
       }
     }' file.txt

Пример запуска

$ cat file.txt
56  6.18  1307  5.73  167  0.564  2  3  1.7  subject_8293748/label/NMA.label
51  3.18  1307  5.73  167  0.564  2  3  1.7  subject_8293755/label/NMA.label
$ awk 'BEGIN {
       a[1]="subject code"
       a[2]="date of birth"
       a[3]="favorite activities"
       a[4]="height (m)"
       a[5]="weight (lbs)"
       a[6]="test score + standard deviation"
       a[7]="color blind"
       a[8]="number of siblings"
       a[9]="average score"
     } {
       print $10
       for(c=0;c++<9;) {
         printf "%-34s%s\n",a[c],$c
       }
     }' file.txt
subject_8293748/label/NMA.label
subject code                      56
date of birth                     6.18
favorite activities               1307
height (m)                        5.73
weight (lbs)                      167
test score + standard deviation   0.564
color blind                       2
number of siblings                3
average score                     1.7
subject_8293755/label/NMA.label
subject code                      51
date of birth                     3.18
favorite activities               1307
height (m)                        5.73
weight (lbs)                      167
test score + standard deviation   0.564
color blind                       2
number of siblings                3
average score                     1.7
$
0
28.04.2021, 23:28

Теги

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