Intereting Posts
Как позволить pacman заметить рубин, установленный rbenv? Почему «ls» спорадически выводит только «.» В корневой каталог внешнего диска? Что означает «Белое пространство» при установке ISO Использование переноса слов с помощью mc «Systemctl list-timers» показывает последние выполненные даты, которые далеки в будущем Проверить последние сообщения Включение настраиваемого журнала аудита в RedHat Как игнорировать пустые каталоги при использовании `rm` с подстановочными знаками для нескольких каталогов в zsh? Перемещение файлов из подпапок в родительскую папку в более крупном каталоге Количество отсчетов подстроки в строке Неплохая идея не иметь раздел подкачки во встроенной Linux-установке? Как переключиться с CLI на GUI Ubuntu Как улучшить производительность Windows при работе внутри KVM Программы не-Ebuild на Gentoo Как обойти проблему «Истек срок действия файла» на локальном зеркале

столбцы в матрицу данных awk

Я ищу решение 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