Использование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
правильно процитирован, а кавычки вокруг hello
удалены, так как теперь это недвусмысленно.
Для принудительного заключения всех полей в кавычки:
$ 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
файлами.
Вы можете автоматизировать и обобщить обработку входного файла, чтобы разрешить любые имена атрибутов и любое количество имен атрибутов, а не только девять, показанные в 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
я передаю в него две внешние переменные с опцией -v
:i=0
и nAtt=9
. i
представляет собой ранг блока данных (, т. е. порядковый номер блока атрибутов во входном файле :file.txt
), а nAtt
— количество атрибутов, которое в этом решении должно быть одинаковым для всех данных. блокировать. awk
видит шаблон table columns are:
, он понимает, что новый блок данных начинается со следующей записи, устанавливает два счетчика i
и ii
и переходит к следующему записывать. 56 6.18 1307 5.73 167 0.564 2 3 1.7 subject_8293748/label/NMA.label
, затем увеличивайте счетчик массива a
ii
и начинайте заполнять массив строками имен атрибутов, пока не достигнете...56 6.18 1307 5.73 167 0.564 2 3 1.7
, за которой следует любое количество символов, напечатать (nAtt+1)
-е поле в этой записи, затем напечатать nAtt
имена и значения атрибутов, по одному в каждой строке, таким образом, чтобы имена атрибутов выравнивались по левому краю и усекались, если их длина превышала 34 символа. Как упоминалось ранее:
внешние переменные могут быть переданы в awk
, например, с помощью:
awk -v i=$i -v nAtt=$nAtt '...'
Насколько статичны ваши данные? Это обман?
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
Вот один из способов
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
$