Выберите уникальные или уникальные значения из списка в сценарии оболочки UNIX - PullRequest
197 голосов
/ 06 марта 2009

У меня есть скрипт ksh, который возвращает длинный список значений, разделенных новой строкой, и я хочу видеть только уникальные / отличные значения. Возможно ли это сделать?

Например, скажем, мой вывод - суффиксы файлов в каталоге:

tar
gz
java
gz
java
tar
class
class

Я хочу увидеть список вроде:

tar
gz
java
class

Ответы [ 7 ]

363 голосов
/ 06 марта 2009

Возможно, вы захотите взглянуть на приложения uniq и sort.

./yourscript.ksh | sort | uniq

(FYI, да, сортировка необходима в этой командной строке, uniq удаляет только дубликаты строк, которые идут сразу после друг друга)

EDIT:

Вопреки тому, что было опубликовано Аароном Дигуллой относительно параметров командной строки uniq:

С учетом следующего ввода:

class
jar
jar
jar
bin
bin
java

uniq выведет все строки ровно один раз:

class
jar
bin
java

uniq -d выведет все строки, которые появляются более одного раза, и напечатает их один раз:

jar
bin

uniq -u выведет все строки, которые появляются ровно один раз, и напечатает их один раз:

class
java
74 голосов
/ 06 марта 2009
./script.sh | sort -u

Это то же самое, что и монооксидный ответ , но более краткий.

9 голосов
/ 06 марта 2009

С zsh вы можете сделать это:

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

Или вы можете использовать AWK:

zsh-4.3.9[t]% awk '!_[$0]++' infile    
tar
more than one word
gz
java
class
9 голосов
/ 06 марта 2009

Для больших наборов данных, где сортировка может быть нежелательна, вы также можете использовать следующий скрипт perl:

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

Это просто запоминает каждую строку вывода, чтобы она не выводила ее снова.

Оно имеет преимущество перед решением "sort | uniq" в том, что не требуется предварительной сортировки.

9 голосов
/ 06 марта 2009

Пропустите их через sort и uniq. Это удаляет все дубликаты.

uniq -d дает только дубликаты, uniq -u дает только уникальные (дубликаты полос).

6 голосов
/ 23 мая 2017

С помощью AWK вы можете сделать, я нахожу это быстрее, чем сортировать

 ./yourscript.ksh | awk '!a[$0]++'
1 голос
/ 29 июля 2012

Уникальный, по запросу, (но не отсортированный);
использует меньше системных ресурсов для менее чем ~ 70 элементов (как проверено временем);
написано для ввода от стандартного ввода,
(или изменить и включить в другой скрипт):
(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[@]}"
...