Выберите уникальные или отдельные значения из списка в оболочке UNIX script
У меня есть ksh script, который возвращает длинный список значений, разделив строку новой строки, и я хочу видеть только уникальные/различные значения. Это можно сделать?
Например, скажем, мой вывод - суффикс файла в каталоге:
tar
gz
java
gz
java
tar
class
class
Я хочу увидеть список вроде:
tar
gz
java
class
Ответы
Ответ 1
Возможно, вы захотите посмотреть приложения uniq
и sort
.
./yourscript.ksh | sort | uniq
(FYI, да, сортировка необходима в этой командной строке, uniq
удаляет только повторяющиеся строки, которые находятся сразу после друг друга)
EDIT:
В отличие от того, что было опубликовано Aaron Digulla в отношении uniq
параметров командной строки:
Учитывая следующий ввод:
class
jar
jar
jar
bin
bin
java
uniq
выводит все строки ровно один раз:
class
jar
bin
java
uniq -d
выводит все строки, которые появляются более одного раза, и они будут печатать их один раз:
jar
bin
uniq -u
выводит все строки, которые появляются ровно один раз, и он будет печатать их один раз:
class
java
Ответ 2
./script.sh | sort -u
Это то же самое, что монооксид , но немного более кратким.
Ответ 3
Протяните их через sort
и uniq
. Это удаляет все дубликаты.
uniq -d
дает только дубликаты, uniq -u
дает только уникальные (дублирует полоски).
Ответ 4
Для больших наборов данных, где сортировка может быть нежелательной, вы также можете использовать следующий perl script:
./yourscript.ksh | perl -ne 'if (!defined $x{$_}) { print $_; $x{$_} = 1; }'
В основном это запоминает каждый вывод строки, чтобы он не выводил его снова.
Он имеет преимущество перед решением "sort | uniq
" в том, что сортировка не требуется спереди.
Ответ 5
С помощью 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
Ответ 6
Уникальный, по запросу (но не отсортированный);
использует меньше системных ресурсов менее чем за 70 элементов (как проверено со временем),
написано для ввода ввода от stdin,
(или изменить и включить в другой script):
(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[@]}"
Ответ 7
С AWK вы можете сделать, я нахожу его быстрее, чем сортировать
./yourscript.ksh | awk '!a[$0]++'