Я ищу решение awk
чтобы получить из этой таблицы (с x количеством имен в столбце 1 и разной длиной столбца 2, который разделен символом “;”):
dataframe.txt:
name1 1;2;4;8 name2 4;5;7 name3 8 name4 11;12 namex 20;21
к этой матрице с присутствующим 1
и отсутствующим 0
:
matrix.txt:
1 2 4 5 7 8 11 12 20 21 name1 1 1 1 0 0 1 0 0 0 0 name2 0 0 1 1 1 0 0 0 0 0 name3 0 0 0 0 0 1 0 0 0 0 name4 0 0 0 0 0 0 1 1 0 0 namex 0 0 0 0 0 0 0 0 1 1
Awk
решение:
awk 'BEGIN{ h = "1 2 3 4 5 6 7 8 11 12 20 21"; len = split(h, head); print "\t\t" h } { printf "%s\t", $1; for (i = 1; i <= len; i++) printf "%s%d", (i == 1? "" : OFS), ($2 ~ "\\<" head[i] "\\>"); print "" }' file
h = "1 2 3 4 5 6 7 8 11 12 20 21"
– строка заголовка len = split(h, head)
– разделить строку h
на заголовок массива, где индексы – это упорядоченные позиции, начиная с 1
а значения являются критическими значениями, полученными путем разделения; len
содержит размер массива print "\t\t" h
– напечатать строку заголовка с начальными символами табуляции printf "%s\t", $1;
– напечатать 1-е поле $1
for (i = 1; i <= len; i++)
- перебирать элементы заголовка
$2 ~ "\\<" head[i] "\\>"
- проверить, содержит ли 2-е поле $2
текущий ansible элемент head[i]
Выход:
1 2 3 4 5 6 7 8 11 12 20 21 name1 1 1 0 1 0 0 0 1 0 0 0 0 name2 0 0 0 1 1 0 1 0 0 0 0 0 name3 0 0 0 0 0 0 0 1 0 0 0 0 name4 0 0 0 0 0 0 0 0 1 1 0 0 namex 0 0 0 0 0 0 0 0 0 0 1 1
Другой подход awk
который сначала генерирует заголовок, а затем заполняет матрицу 1 для каждого ключа в заголовке массива, существует в текущей строке ввода, в противном случае – 0, если не существует.
Мы использовали grep
для извлечения только -o
чисел, которые соответствуют пустой строке по левому краю числа \b
(так же, как \<
мы использовали в awk
для левой и правой сторон).
awk 'NR==FNR { !head[$1]++; next } { printf $1; for (x in head) { printf (x?FS:"") ($0 ~ "\\<" x "\\>") }; print "" }' <(grep -o '\b[0-9]\+' infile) infile
Выход:
name1 1 1 1 0 0 1 0 0 0 0 name2 0 0 1 1 1 0 0 0 0 0 name3 0 0 0 0 0 1 0 0 0 0 name4 0 0 0 0 0 0 1 1 0 0 namex 0 0 0 0 0 0 0 0 1 1
Вы можете сгенерировать заголовок и вставить в первую строку во входном файле, тогда awk
будет простым как:
awk 'NR==1{ split($0, head); next } { printf $1; for (x in head){ printf (x?FS:"") ($2 ~ "\\<" head[x] "\\>" ) }; print "" }' infile