Wählen Sie einzigartige oder verschiedene Werte aus einer Liste in UNIX-Shell-Skript
Frage
Ich habe ein KSH-Skript, das eine lange Liste von Werten zurückgibt, Newline getrennt, und ich möchte nur die eindeutigen / unterschiedlichen Werte sehen. Es ist möglich, dies zu tun?
Zum Beispiel, sagen meine Ausgabe ist Dateiendung in einem Verzeichnis:
tar gz java gz java tar class class
Ich möchte eine Liste, um zu sehen, wie:
tar gz java class
Lösung
Sie können an den uniq
und sort
Anwendungen suchen.
./yourscript.ksh | sort | uniq
(FYI, ja, die Art in dieser Befehlszeile erforderlich ist, uniq
nur Streifen doppelte Zeilen, die unmittelbar hintereinander sind)
EDIT:
Im Gegensatz zu dem, was von Aaron Digulla in Bezug auf die Kommandozeile uniq
Optionen:
In Anbetracht der folgende Eingabe:
class jar jar jar bin bin java
uniq
Gibt alle Zeilen genau einmal:
class jar bin java
uniq -d
Gibt alle Zeilen, die mehr als einmal erscheinen, und es wird sie einmal drucken:
jar bin
uniq -u
gibt alle Linien, die genau einmal erscheinen, und es wird sie einmal drucken:
class java
Andere Tipps
./script.sh | sort -u
Dies ist die gleiche wie Monoxid des Antwort , aber ein bisschen mehr prägnant.
Für größere Datenmengen, wo möglicherweise nicht wünschenswert sein, sortieren, können Sie auch folgenden Perl-Skript verwenden:
./yourscript.ksh | perl -ne 'if (!defined $x{$_}) { print $_; $x{$_} = 1; }'
Diese im Grunde erinnert sich nur jede Zeile ausgegeben, so dass es nicht ausgibt es wieder.
Es hat den Vorteil gegenüber der „sort | uniq
“ Lösung, dass es keine Sortierung nach vorne erforderlich.
Mit zsh Sie können dies tun:
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
Sie können auch AWK verwenden:
zsh-4.3.9[t]% awk '!_[$0]++' infile
tar
more than one word
gz
java
class
Rohr sie durch sort
und uniq
. Dadurch werden alle Duplikate.
uniq -d
gibt nur die Duplikate, uniq -u
gibt nur die Einzigen (Streifen Duplikate).
Mit AWK Sie tun können, finde ich es schneller als Art
./yourscript.ksh | awk '!a[$0]++'
Unique, wie gewünscht, (aber nicht sortiert);
verwendet weniger Systemressourcen für weniger als ~ 70 Elemente (wie mit der Zeit getestet);
geschrieben Eingang nehmen von stdin,
(Oder ändern, und dies in einem anderen Skript):
(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[@]}"