Сортировка по отдельности из строки

Сортировка по отдельности из строки

Можете ли вы дать мне предложение, как мне сделать уникальную сортировку из строки или ряда? У меня есть такая информация:

Special   c1,c2,c5,c7,c1,c2   
Special2  C6

(это символ табуляции между Specialи c1...).

Я хочу получить такой результат:

Special   c1,c2,c5,c7  
Special2  C6

Как мне этого добиться?

решение1

С использованиемэтот ответ,

perl -MList::MoreUtils=uniq -laF'\t' -ne '
    $F[1] = join(",", uniq(sort(split(",", $F[1])))); print join("\t", @F)'

Это зависит от внешнего пакетаСписок::MoreUtils. Если вы не хотите устанавливать внешнюю зависимость, переопределите uniqфункциюеще несколько строк Perl. (Хотя у меня он, кажется, установлен как часть базовой системы на macOS.)

решение2

perl -F'\t|,' -lane 'my %h; print shift @F, "\t", join ",", sort grep !$h{$_}++, @F' dataf

Объяснение

  • -F'\t|,'=> разделит каждое поле записи на массив @Fпо TABили commaсимволов.
  • -lтакже установит значения RSto newlineи ORSto .newline
  • -aавтоматически разделит каждую запись на слова на основе FSвыбранного -F.
  • -nустановит неявный цикл чтения записей на входе ANDи будет печатать данные только по запросу.
  • -eэто Perlкод, который будет выполняться для каждой записи входных данных на основе RSвыбранного -lвыше.
  • Первый элемент будет задан, shiftа остальные элементы будут uniquifiedсохранены как ключи хэша, %hкоторый будет регенерироваться каждый раз при считывании записи. Затем уникальные элементы сортируются, объединяются запятой и выводятся на печать.

решение3

Протестировано с OpenBSD awk, GNU awkи mawk:

awk -F ',| +' '{ for (i = 2; i <= NF; ++i) { print $1, $i } }' data.in |
sort -u |
awk '{ f[$1] = (f[$1] ? f[$1] "," : "") $2 } END { for (k in f) { print k, f[k] } }'

Первый awkрасширяет заданные данные до

Special c1
Special c2
Special c5
Special c7
Special c1
Special c2
Special2 C6

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

В sortсередине сортирует его по

Special2 C6
Special c1
Special c2
Special c5
Special c7

Он выполняет сортировку, используя полную строку в качестве ключа сортировки, и отбрасывает все повторяющиеся строки.

Последний awkрекомбинирует данные в

Special c1,c2,c5,c7
Special2 C6

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

решение4

Другой способ в одну строку:

while read line; do echo "$line" | awk '{print $1}' | tr '\n' ' ';  echo "$line" | awk '{print $2}' | tr ',' '\n' | sort -u | tr '\n' ',' | sed -e 's/.$//g'; echo; done < file_to_sort

Он берет первый столбец каждой строки ( echo $line | awk '{print $1}' | tr '\n' ' ';) и сортирует значения второго столбца, разделенные символом «,», после преобразования его в один столбец для применения sort, а затем преобразует его обратно в одну строку с исходным форматированием ( echo $line | awk '{print $2}' | tr ',' '\n' | sort -u | tr '\n' ',').

Делаем разбиение строк, как предлагает @tripleee:

while IFS=$'\t' read first second; do printf "%s\t%s\n" "$first" "$(tr ',' '\n' <<<"$second" | sort | tr '\n' ',' | sed -e 's/.$//g';)"; done < file_to_sort

Связанный контент