Выберите уникальные или отличные значения из списка в сценарии оболочки UNIX

StackOverflow https://stackoverflow.com/questions/618378

Вопрос

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

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

tar
gz
java
gz
java
tar
class
class

Я хочу увидеть список, подобный:

tar
gz
java
class
Это было полезно?

Решение

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

./yourscript.ksh | sort | uniq

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

Редактировать:

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

Учитывая следующие входные данные:

class
jar
jar
jar
bin
bin
java

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

class
jar
bin
java

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

jar
bin

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

class
java

Другие советы

./script.sh | sort -u

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

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

./yourscript.ksh | perl -ne 'if (!defined $x{

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

<*>

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

Он имеет преимущество перед сортировкой | Uniq & Quot; Решение в том, что не требуется сортировка заранее.

}) { print

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

<*>

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

Он имеет преимущество перед сортировкой | Uniq & Quot; Решение в том, что не требуется сортировка заранее.

; $x{

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

<*>

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

Он имеет преимущество перед сортировкой | Uniq & Quot; Решение в том, что не требуется сортировка заранее.

} = 1; }'

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

Он имеет преимущество перед сортировкой | Uniq & Quot; Решение в том, что не требуется сортировка заранее.

С помощью 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 '!_[<*>]++' infile    
tar
more than one word
gz
java
class

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

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

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

 ./yourscript.ksh | awk '!a[<*>]++'

Уникальный, по запросу, (но не отсортированный);
использует меньше системных ресурсов для менее чем ~ 70 элементов (как проверено временем);
написано для ввода от stdin,
(или изменить и включить в другой скрипт):
(Бака)

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[@]}"
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top