Выберите уникальные или отличные значения из списка в сценарии оболочки UNIX
Вопрос
У меня есть скрипт 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[@]}"