2009-03-06 10 views

Odpowiedz

302

może chcesz aby przejrzeć aplikacje uniq i sort.

 
./yourscript.ksh | sort | uniq 

(FYI, tak, sort jest konieczne w tym wierszu poleceń, uniq paski tylko zduplikowane linie, które są bezpośrednio po siebie)

EDIT:

Wbrew temu, co zostało opublikowane przez Aaron Digulla w odniesieniu do opcji linii poleceń uniq:

Podane dane wejściowe:

 
class 
jar 
jar 
jar 
bin 
bin 
java 

uniq wyjścia będą wszystkie linie dokładnie jeden raz:

 
class 
jar 
bin 
java 

uniq -d wyjścia będą wszystkie linie, które pojawiają się więcej niż raz, a będzie je wydrukować raz:

 
jar 
bin 

uniq -u wyjście wola wszystkich linie, które pojawiają się dokładnie jeden raz, i zostaną wydrukowane raz:

 
class 
java 
+1

Tylko FYI dla spóźnialców: odpowiedź AaronDigulla została skorygowana. – mklement0

+1

Bardzo dobry punkt to "sortowanie jest konieczne w tym wierszu poleceń, uniq tylko usuwa zduplikowane linie, które są zaraz po sobie", których właśnie się nauczyłem !! – HattrickNZ

+2

GNU 'sort' zawiera wersję' -u', która nadaje również unikalne wartości. – Arthur2e5

9

Przetestuj je przez sort i uniq. Spowoduje to usunięcie wszystkich duplikatów.

uniq -d podaje tylko duplikaty, uniq -u podaje tylko te unikalne (usuwa duplikaty).

+0

Najpierw sortuj według jej wyglądu. – Brabster

+1

Tak, robisz. Lub dokładniej, musisz zgrupować wszystkie zduplikowane linie razem. Sortowanie robi to z definicji;) –

+0

Również 'uniq -u' nie jest domyślnym zachowaniem (zobacz edycję w mojej odpowiedzi dla szczegółów). –

9

przypadku większych zbiorów danych, gdzie sortowanie nie może być pożądane, można również użyć poniższy skrypt perla:

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

To w zasadzie tylko pamięta każde wyjście liniowe, tak aby nie wyprowadzać go ponownie.

Ma tę przewagę nad rozwiązaniem "sort | uniq", że nie wymaga sortowania z góry.

+2

Należy zauważyć, że sortowanie bardzo dużego pliku nie jest problemem samo w sobie z sortowaniem; może sortować pliki większe niż dostępna pamięć RAM + zamiana. Perl, OTOH, zawiedzie, jeśli jest tylko kilka duplikatów. –

+0

Tak, jest to kompromis w zależności od oczekiwanych danych. Perl jest lepszy w przypadku ogromnego zestawu danych z wieloma duplikatami (nie jest wymagana pamięć dyskowa). Ogromny zestaw danych z kilkoma duplikatami powinien używać sortowania (i pamięci dyskowej). Mogą być również używane małe zestawy danych. Osobiście najpierw spróbowałbym Perla, przełączałbym się, by sortować, jeśli się nie powiedzie. – paxdiablo

+0

Od sortowania daje tylko korzyści, jeśli ma zamiany na dysk. – paxdiablo

9

Z zsh można to zrobić:

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 

Albo można użyć AWK:

zsh-4.3.9[t]% awk '!_[$0]++' infile  
tar 
more than one word 
gz 
java 
class 
+2

Sprytne rozwiązania, które nie wymagają sortowania danych wejściowych. Ostrzeżenia: Bardzo sprytne, ale tajemnicze rozwiązanie 'awk' (patrz http://stackoverflow.com/a/21200722/45375 dla wyjaśnienia) będzie działać z dużymi plikami, o ile liczba unikalnych linii jest mała wystarczy (ponieważ unikalne linie są przechowywane w pamięci). Rozwiązanie 'zsh' wczytuje najpierw cały plik do pamięci, co może nie być opcją dla dużych plików. Ponadto, jak napisano, tylko linie bez osadzonych spacji są obsługiwane poprawnie; aby to naprawić, użyj 'IFS = $ '\ n' read -d '' -r -A u mklement0

+0

Prawidłowo. Lub: '(IFS = $ '\ n' u = ($ (

+1

Dzięki, to jest prostsze (zakładając, że nie potrzebujesz ustawić zmienne potrzebne poza podpowłoką). Ciekawi mnie, kiedy potrzebny jest przyrostek '[@] do odniesienia się do wszystkich elementów tablicy - wydaje się, że - przynajmniej od wersji 5 - działa bez niego; czy po prostu dodajesz to dla jasności? – mklement0

59
./script.sh | sort -u 

To jest taka sama jak monoxide'sanswer, ale nieco bardziej zwięzłe.

+4

Jesteś skromny: twoje rozwiązanie będzie również _perform_ lepsze (prawdopodobnie zauważalne tylko w przypadku dużych zestawów danych). – mklement0

1

Unikalne, zgodnie z życzeniem, (ale nie posortowane);
wykorzystuje mniej zasobów systemowych dla mniej niż ~ 70 elementów (zgodnie z testem z czasem);
napisany wziąć wejściowe ze standardowego wejścia,
(lub modyfikować i to w innym skrypcie):
(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[@]}" 
2

Z AWK można zrobić, znaleźć go szybciej niż porządek

./yourscript.ksh | awk '!a[$0]++' 
Powiązane problemy