
¿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 Special
y 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, uniq
es 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@F
de caracteresTAB
ocomma
.-l
establecerá elRS
tonewline
yORS
elnewline
también.-a
dividirá automáticamente cada registro en palabras según loFS
elegido por-F
.-n
configurará un registro implícito leído en bucle en la entradaAND
imprimirá cosas solo cuando se le solicite.-e
es elPerl
código que se ejecutará en cada registro de la entrada segúnRS
lo elegido-l
anteriormente.- El primer elemento estará dado por
shift
y los elementos restantes se almacenaránuniquified
como claves de un hash,%h
que 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 awk
y 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 awk
expande 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 sort
del 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 awk
recombina 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 sort
y 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