Selezionare valori univoci o distinti da un elenco nello script della shell UNIX
Domanda
Ho uno script ksh che restituisce un lungo elenco di valori, newline separati, e voglio vedere solo i valori univoci / distinti. È possibile farlo?
Ad esempio, supponiamo che il mio output sia suffissi di file in una directory:
tar gz java gz java tar class class
Voglio vedere un elenco come:
tar gz java class
Soluzione
Potresti voler guardare le applicazioni uniq
e sort
.
./yourscript.ksh | sort | uniq
(Cordiali saluti, sì, l'ordinamento è necessario in questa riga di comando, uniq
rimuove solo le linee duplicate che si trovano immediatamente una dopo l'altra)
Modifica
Contrariamente a quanto è stato pubblicato da Aaron Digulla in relazione alle opzioni della riga di comando di uniq
:
Dato il seguente input:
class jar jar jar bin bin java
uniq
produrrà tutte le righe esattamente una volta:
class jar bin java
uniq -d
produrrà tutte le righe che appaiono più di una volta e le stamperà una volta:
jar bin
uniq -u
produrrà tutte le righe che appaiono esattamente una volta e le stamperanno una volta:
class java
Altri suggerimenti
./script.sh | sort -u
È lo stesso di monoxide's rispondi , ma un po 'più conciso.
Per set di dati più grandi in cui l'ordinamento potrebbe non essere desiderabile, puoi anche utilizzare il seguente script perl:
./yourscript.ksh | perl -ne 'if (!defined $x{ Per set di dati più grandi in cui l'ordinamento potrebbe non essere desiderabile, puoi anche utilizzare il seguente script perl:
<*>
Questo in pratica ricorda solo ogni output di linea in modo che non lo ritorni più.
Ha il vantaggio rispetto all'ordinamento | uniq
" soluzione in quanto non è necessario un ordinamento anticipato.
}) { print Per set di dati più grandi in cui l'ordinamento potrebbe non essere desiderabile, puoi anche utilizzare il seguente script perl:
<*>
Questo in pratica ricorda solo ogni output di linea in modo che non lo ritorni più.
Ha il vantaggio rispetto all'ordinamento | uniq
" soluzione in quanto non è necessario un ordinamento anticipato.
; $x{ Per set di dati più grandi in cui l'ordinamento potrebbe non essere desiderabile, puoi anche utilizzare il seguente script perl:
<*>
Questo in pratica ricorda solo ogni output di linea in modo che non lo ritorni più.
Ha il vantaggio rispetto all'ordinamento | uniq
" soluzione in quanto non è necessario un ordinamento anticipato.
} = 1; }'
Questo in pratica ricorda solo ogni output di linea in modo che non lo ritorni più.
Ha il vantaggio rispetto all'ordinamento | uniq
" soluzione in quanto non è necessario un ordinamento anticipato.
Con zsh puoi farlo:
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
Oppure puoi usare AWK:
zsh-4.3.9[t]% awk '!_[<*>]++' infile
tar
more than one word
gz
java
class
Instradali attraverso sort
e uniq
. Questo rimuove tutti i duplicati.
uniq -d
fornisce solo i duplicati, uniq -u
fornisce solo quelli unici (rimuove i duplicati).
Con AWK puoi farlo, lo trovo più veloce dell'ordinamento
./yourscript.ksh | awk '!a[<*>]++'
Unico, come richiesto, (ma non ordinato);
utilizza meno risorse di sistema per meno di ~ 70 elementi (come testato nel tempo);
scritto per ricevere input da stdin,
(o modifica e includi in un altro 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[@]}"