Ordenar únicamente desde una fila

Ordenar únicamente desde una fila

¿Puede darme una sugerencia sobre cómo puedo ordenar de forma única desde una línea o fila? Tengo información como esta:

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

(Ese es un carácter TAB entre Specialy c1...).

Quiero el resultado como este:

Special   c1,c2,c5,c7  
Special2  C6

¿Cómo puedo lograr esto?

Respuesta1

Usandoesta respuesta,

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

Esto depende de un paquete externo.Lista::MásUtilidades. Si no desea instalar una dependencia externa, uniqes posible volver a implementar la función.sólo unas pocas líneas más de Perl. (Aunque parece que lo tengo instalado como parte del sistema base en macOS).

Respuesta2

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

Explicación

  • -F'\t|,'=> dividirá los campos de cada registro en una matriz @Fde caracteres TABo comma.
  • -lestablecerá el RSto newliney ORSel newlinetambién.
  • -adividirá automáticamente cada registro en palabras según lo FSelegido por -F.
  • -nconfigurará un registro implícito leído en bucle en la entrada ANDimprimirá cosas solo cuando se le solicite.
  • -ees el Perlcódigo que se ejecutará en cada registro de la entrada según RSlo elegido -lanteriormente.
  • El primer elemento estará dado por shifty los elementos restantes se almacenarán uniquifiedcomo claves de un hash, %hque se regenerará cada vez que se lea un registro. Luego, los elementos únicos se ordenan, se unen con una coma y se imprimen.

Respuesta3

Probado con OpenBSD awk, GNU awky 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] } }'

El primero awkexpande los datos dados en

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

Utiliza comas y espacios múltiples como delimitador de campo y, para cada registro (línea) de entrada, imprime el primer campo seguido de cada uno de los demás campos en líneas separadas. Esto supone que no hay otros espacios o comas en las líneas excepto donde se interpretarán correctamente como delimitadores.

El sortdel medio lo clasifica en

Special2 C6
Special c1
Special c2
Special c5
Special c7

Realiza una clasificación utilizando la línea completa como clave de clasificación y descarta cualquier línea duplicada.

El último awkrecombina los datos en

Special c1,c2,c5,c7
Special2 C6

Para ello, utiliza el primer campo como clave en una matriz asociativa y almacena la concatenación separada por comas de los datos correspondientes en el segundo campo como valor. Al final, se imprimen todos los datos recopilados.

Respuesta4

Otra forma en una línea:

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

Toma la primera columna de cada línea ( echo $line | awk '{print $1}' | tr '\n' ' ';) y ordena los valores de la segunda columna separados por ',' después de convertirla en una sola columna para aplicarla sorty luego convertirla nuevamente a una sola fila con el formato original ( echo $line | awk '{print $2}' | tr ',' '\n' | sort -u | tr '\n' ',').

Haciendo división de líneas como lo sugiere @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

información relacionada