Объединить столбец на основе 2-го столбца

Страница руководства - это то место, куда можно перейти, для параметров:

-fn список шрифтов
Выберите шрифты, которые будут использоваться. Это список имен шрифтов , разделенных запятыми, которые проверяются по порядку при попытке найти глифы для символов. Первый шрифт определяет размер ячейки для символов; другие шрифты могут быть меньше, но (как правило) не больше. К нему всегда добавляется (надеюсь) разумный список шрифтов по умолчанию. См. Дополнительные сведения о шрифте ресурса.

и настройки ресурсов:

шрифт : список шрифтов
Выберите шрифты, которые будут использоваться. Это список имен шрифтов , разделенных запятыми, которые проверяются по порядку при попытке найти глифы для символов. Первый шрифт определяет размер ячейки для символов; другие шрифты могут быть меньше, но (как правило) не больше. К нему всегда добавляется (надеюсь) разумный список шрифтов по умолчанию; опция -fn .

Каждый шрифт может быть именем стандартного основного шрифта X11 (XLFD) с необязательным префиксом «x:» или шрифтом Xft (Compile xft) с префиксом «xft:» .

Учитывая комментарий @thrig, вы должны иметь возможность сделать это:

urxvt.font:     xft:DejaVu Sans Mono, xft:Noto Emoji

(если у вас установлены эти шрифты).

Однако пакет google-noto-emoji-fonts в Fedora24 выглядит шрифтом смешанной ширины, который urxvt не обрабатывает, что дает следующее сообщение:

$ urxvt -fn 'xft:DejaVu Sans Mono,xft:Noto Emoji'                               
urxvt: unable to calculate font width for 'Noto Emoji:slant=0:weight=100:pixelsize=19:minspace=True', ignoring.

Согласно отчету об ошибке Font-Awesome Не может использоваться с urxvt # 3681 , urxvt не проверяет ширину глифов в области частного использования (т. Е. Нестандартизировано). Это относится к любому из шрифтов Emoji.

Если вас интересуют только Emoji, urxvt работает только с этим шрифтом (и использует ячейки двойной ширины для всего):

urxvt -fn 'xft:Noto Emoji'

urxvt in the background

1
31.07.2016, 11:17
5 ответов

С двумерными массивами, найденными в GNU awk

awk -F, '{
  a[$2][$1]
  }
  END{
    for (i in a) {
      c=0; printf "%s,", i; 
        for (j in a[i]) {
          ++c; printf "%s%s", j, length(a[i]) == c? "\n": "-"
          }
     }
   }' file
1
27.01.2020, 23:10

В perl:

#! /usr/bin/perl

use strict;
my %mergecol = ();

while(<>) {
  s/#.*//;            # strip comments
  next if (m/^\s*$/); # skip empty lines
  chomp;
  my ($val,$key) = split ',';
  push @{ $mergecol{$key} }, $val;
};

foreach my $k (keys %mergecol) { 
  printf "%s,%s\n", $k, join('-', @{ $mergecol{$k} } );
}

Цикл while читает входные данные и создает структуру Hash-of-Arrays (HoA) - ассоциативный массив, где каждый элемент является массивом (он же "список"). Ключами хэша являются вторые поля, а элементами каждого списка - первые поля строк с тем же вторым полем.

В конце скрипта распечатывается HoA по одной строке на запись, с именем ключа, запятой, а затем элементы, соединенные -.

выполнить как:

$ ./rock.pl rock.txt
254341,gcmj7krrx5x6nf8r
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254344,hguvgstqxu3gowfg
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3

Или сократить и вставить в команду оболочки или сценарий как "однострочный текст":

$ perl -n -e '
    s/#.*//;
    next if (m/^\s*$/);
    chomp; ($v,$k)=split ","; push @{ $mc{$k} }, $v;
    END {
     foreach $k (keys %mc) { printf "%s,%s\n", $k, join("-",@{$mc{$k}}) }
    }' rock.txt 

Или

$ perl -e 'while(<>) {s/#.*//;next if (m/^\s*$/);chomp;($v,$k)=split ",";push @{$mc{$k}}, $v};
    foreach $k (keys %mc) {printf "%s,%s\n",$k,join("-",@{$mc{$k}})}' rock.txt

Обратите внимание, что хэш или ассоциативный массив по своей природе неупорядочен, если вам нужен отсортированный вывод, либо передайте в sort, либо используйте (sort keys %f) в строках foreach my $k выше.

3
27.01.2020, 23:10

With GNU datamash:

datamash -t, -s -g 2 collapse 1 <data.txt | sed 's/,/-/2g'

Result:

254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254341,gcmj7krrx5x6nf8r
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254344,hguvgstqxu3gowfg
6
27.01.2020, 23:10

В развитие ответа sjsam'а, но проще:

awk -v FS="," '
    {
            f2[$2] = f2[$2] "-" $1   # append "-" and $1 to the current value
    }
    END {   # This code will be processed at the end
            for (i in f2) {  # for all the indexes i in f2
                             # (i.e., each unique value from column 2)
                             # print one line in the desired format
                printf "%s,%s\n", i, gensub("-", "", 1, f2[i])
            }
    }
'

Эта программа простодушно строит строки, которые выглядят так:

   -       pw1jc5ssyt6hx618      -       pht92h4adr3mrbz3      -       alnac47rt8d4ege3
(hyphen)       (value)        (hyphen)       (value)        (hyphen)       (value)

(но без пробелов, они просто для подсветки).  Затем, когда приходит время печатать данные, он удаляет первые - с помощью общей функции подстановки, gensub().  К сожалению, это не поддерживается в спецификации POSIX для awk; для этого требуется GNU Awk.  В качестве альтернативы можно изменить gensub("-", "", 1, f2[i]) на substr(f2[i], 2) и получить подстроку f2[i] от второго символа до конца (т.е. все, кроме первого символа, а это -), способом, соответствующим стандарту POSIX.

При этом будет (сделана попытка) обработать каждую строку во входных данных.  Если во входных данных есть строки, которые должны быть проигнорированы. (например, пустые строки), вы можете изменить первую часть на

    /./ {
            f2[$2] = f2[$2] "-" $1   # …
    }

или

    NF==2 {
            f2[$2] = f2[$2] "-" $1   # …
    }

Когда я запускаю ответ sjsam или свой собственный, я получаю

254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254341,gcmj7krrx5x6nf8r
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254344,hguvgstqxu3gowfg

т.е. сортировку по значению ключа столбца 2.  Вы показываете желаемый результат в порядке первого появления ключа столбца 2 во входных данных.  Если это важно для вас, попробуйте:

awk -v FS="," '
    {
            if (! ($2 in f2)) appearance[++x] = $2
            f2[$2] = f2[$2] "-" $1   # append "-" and $1 to the current value
    }
    END {   # This code will be processed at the end
            for (ix in appearance) {
                             # for all the indexes i in f2
                             # (i.e., each unique value from column 2)
                             # print one line in the desired format
                i = appearance[ix]
                printf "%s,%s\n", i, gensub("-", "", 1, f2[i])
            }
    }
'

который использует массив appearance для отслеживания порядка появления.

2
27.01.2020, 23:10

awk — ваш друг

$ cat 299360
ipw1jc5ssyt6hx618,254343
ysezaratlycpuggl,254333
pht92h4adr3mrbz3,254343
hguvgstqxu3gowfg,254344
gqjp2rsjmk1a2v9c,254333
twdzyi2ddbnrfknd,254333
gcmj7krrx5x6nf8r,254341
tpqorqbyrg1nmm7s,254333
alnac47rt8d4ege3,254343
$ awk -v FS="," '/^$/{next} # for empty line go to next record
                {if(NR==1){ # checking for first record
                f2[$2]=$1;next} # Adding $1 to array f2 at index $2
                else{
                if($2 in f2){ # Check if $2 is already an index in f2
                f2[$2]=f2[$2]"-"$1;next #appending "-$1" to current value
                }
                else{
                f2[$2]=$1;next
                }
                }}
                END{ # This line will be processed at the end
                for(i in f2){  # for all the indexes i in f2
                printf "%s,%s\n",i,f2[i] #printing in the desired format
                }
                }
                ' 299360
254341,gcmj7krrx5x6nf8r
254333,ysezaratlycpuggl-gqjp2rsjmk1a2v9c-twdzyi2ddbnrfknd-tpqorqbyrg1nmm7s
254343,pw1jc5ssyt6hx618-pht92h4adr3mrbz3-alnac47rt8d4ege3
254344,hguvgstqxu3gowfg

Объяснение

  1. FS="," — FS — это встроенная переменная awk, которая расшифровывается как разделитель полей. Установка разделителя полей на , установит , в качестве разделителя.
  2. Вы получаете доступ к полям по $1, $2 и так далее.
  3. Скрипт awk заключен в одинарные кавычки; т.е. 'awk-script-goes-here'
  4. NR является встроенной переменной awk, которая обозначает номер записи (номер обрабатываемой в настоящее время записи). По умолчанию каждая строка является записью.
  5. С помощью f2[$2]=$1 мы устанавливаем ассоциативный массив f2 с полем2 (т.е. $2) в качестве индекса.
  6. $2 в f2 проверяет, присутствует ли индекс в массиве.
  7. if-else и printf говорят сами за себя.
  8. Блок END в awk выполняется только в самом конце; т.е. после того, как все записи были обработаны.
  9. for(i in f2) — конструкция цикла for, используемая для синтаксического анализа ассоциативных массивов в awk. Это другой способ сказать, для каждого индекса i в f2 сделайте что-нибудь
  10. Обратите внимание, что приведенный выше цикл for может не печатать массив в порядке. Однако вы можете использовать команду sort bash для сортировки массива.
  11. next переходит к следующей записи без обработки последующих команд.
  12. /pattern/ проверяет наличие паттерна в awk; шаблон ^$ проверяет наличие пустой строки.

Ссылка

Если вы хотите стать экспертом в awk, Эффективное программирование awk обязательно к прочтению.

Уродливая однострочная

awk -v FS="," '/^$/{next}{if(NR==1){f2[$2]=$1;next}else{if($2 in f2){f2[$2]=f2[$2]"-"$1;next}else{f2[$2]=$1;next}}}END{for(i in f2){printf "%s,%s\n",i,f2[i]}}' 299360

Примечание: В идеале не стоит жестко кодировать новые строки в скриптах awk, как в printf "%s,%sn",i,f2[i]. Вы можете заменить его на printf "%s,%sn",i,f2[i];p rint для дополнительной переносимости.

6
27.01.2020, 23:10

Теги

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