Seleccione valores únicos o distintos de una lista en el script de shell de UNIX


Tengo un script ksh que devuelve una larga lista de valores, separados por una nueva línea, y quiero ver solo los valores únicos/distintos. Es posible hacer esto?

Por ejemplo, digamos que mi salida son sufijos de archivo en un directorio:

tar
gz
java
gz
java
tar
class
class

Quiero ver una lista como:

tar
gz
java
class
Author: brabster, 2009-03-06

7 answers

Es posible que desee mirar las aplicaciones uniq y sort.

./yourscript.ksh | sort | uniq

(Para su información, sí, la ordenación es necesaria en esta línea de comandos, uniq solo elimina las líneas duplicadas que están inmediatamente una tras otra)

EDITAR:

Contrario a lo que ha sido publicado por Aaron Digulla en relación con las opciones de la línea de comandos de uniq:

Dada la siguiente entrada:

class
jar
jar
jar
bin
bin
java

uniq mostrará todas las líneas exactamente una vez:

class
jar
bin
java

uniq -d mostrará todas las líneas que aparecen más de una vez, y las imprimirá una vez:

jar
bin

uniq -u mostrará todas las líneas que aparecen exactamente una vez, y las imprimirá una vez:

class
java
 327
Author: Matthew Scharley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 10:31:38
./script.sh | sort -u

Esto es lo mismo que el monóxido de respuesta , pero un poco más concisa.

 68
Author: gpojd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:30

Para conjuntos de datos más grandes donde la ordenación puede no ser deseable, también puede usar el siguiente script de perl:

./yourscript.ksh | perl -ne 'if (!defined $x{$_}) { print $_; $x{$_} = 1; }'

Esto básicamente solo recuerda cada salida de línea para que no lo haga de nuevo.

Tiene la ventaja sobre la solución "sort | uniq" en que no se requiere clasificación por adelantado.

 9
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-03-06 11:02:43

Con zsh puedes hacer esto:

zsh-5.0.0[t]% cat infile 
tar
more than one word
gz
java
gz
java
tar
class
class
zsh-5.0.0[t]% print -l "${(fu)$(<infile)}"
tar
more than one word
gz
java
class

O puedes usar AWK:

zsh-4.3.9[t]% awk '!_[$0]++' infile    
tar
more than one word
gz
java
class
 9
Author: Dimitre Radoulov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-18 17:29:36

Pipe a través de sort y uniq. Esto elimina todos los duplicados.

uniq -d da solo los duplicados, uniq -u da solo los únicos (tiras duplicados).

 9
Author: Aaron Digulla,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-29 11:25:12

Con AWK puedes hacerlo, lo encuentro más rápido que sort

 ./yourscript.ksh | awk '!a[$0]++'
 6
Author: Ajak6,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-22 21:27:52

Único, según lo solicitado, (pero no ordenado);
utiliza menos recursos del sistema para menos de ~70 elementos (según lo probado con el tiempo);
escrito para tomar entrada de stdin,
(o modificar e incluir en otro script):
(Bash)

bag2set () {
    # Reduce a_bag to a_set.
    local -i i j n=${#a_bag[@]}
    for ((i=0; i < n; i++)); do
        if [[ -n ${a_bag[i]} ]]; then
            a_set[i]=${a_bag[i]}
            a_bag[i]=$'\0'
            for ((j=i+1; j < n; j++)); do
                [[ ${a_set[i]} == ${a_bag[j]} ]] && a_bag[j]=$'\0'
            done
        fi
    done
}
declare -a a_bag=() a_set=()
stdin="$(</dev/stdin)"
declare -i i=0
for e in $stdin; do
    a_bag[i]=$e
    i=$i+1
done
bag2set
echo "${a_set[@]}"
 1
Author: FGrose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-31 03:54:19