Как создать массив уникальных элементов от строки/массива в ударе?

Можно всегда использовать функцию:

backup()
  for i do
    case ${i##*/} in
      (?*.?*) cp -iv -- "$i" "${i%.*}.bak.${i##*.}";;
      (*) cp -iv -- "$i" "$i.bak"
    esac
  done

${i##*/} базовое имя $i (который является $i со всем до самого правого / удаленный), потому что мы не хотим рассматривать bar/file как расширение в foo.bar/file.

Затем мы проверяем ли $i содержит расширение, это - то, если оно содержит по крайней мере один dot символ с символами с обеих сторон (?* любой символ, сопровождаемый 0 или больше символами, таким образом, это - один или несколько символов). Мы не можем сделать *.* иначе мы скопировали бы ~/.bashrc как ~/.bak.bashrc например.

Тем синтаксисом выше является POSIX за исключением -v (для подробного) опция к cp который является расширением GNU, также найденным в нескольких других реализациях как BSDs'.

Затем можно сделать вещи как:

backup foo.php bar.html baz<Tab>...

Или:

backup *.php

Не имея необходимость волноваться о проигрывающих данных (-i попросит подтверждение прежде, чем перезаписать файл, видеть также -b опция с GNU cp) или не выбирая правильное имя.

8
10.11.2014, 19:36
5 ответов

удара С GNU awk (это также сохраняет первоначальный заказ)

printf '%s\n' "1 2 3 2 1" | awk -v RS='[[:space:]]+' '!a[$0]++{printf "%s%s", $0, RT}'
1 2 3 

К читает в удар массив

read -ra arr<<<$(printf '%s\n' "1 2 3 2 1" |
 awk -v RS='[[:space:]]+' '!a[$0]++{printf "%s%s", $0, RT}')
printf "%s\n"  "${arr[@]}"
1
2
3
4
27.01.2020, 20:09

Это решение работало для меня.

ids=(1 2 3 2 1)
echo "${ids[@]}" | tr ' ' '\n' | sort -u | tr '\n' ' '

Вышеуказанное производит 1 2 3 в качестве выхода.

Более короткая версия, предложенная костами, может быть,

printf "%s\n" "${ids[@]}" | sort -u | tr '\n' ' '

для хранения конечных результатов на массив, вы можете сделать что-то вроде,

IFS=$' '
arr=($(printf "%s\n" "${ids[@]}" | sort -u | tr '\n' ' '))
unset IFS

сейчас, когда я делаю эхо на ART , это это выход, который я получаю.

echo "${arr[@]}"
1 2 3

Список литературы

https://stackovflow.com/a/13648438/1742825 https://stackoverflow.com/a/9449633/1742825

1
27.01.2020, 20:09

Чтобы сделать это полностью в оболочке и поместить результат в массиве,

declare -A seen
for word in one two three two one
do
        if [ ! "${seen[$word]}" ]
        then
                result+=("$word")
                seen[$word]=1
        fi
done
echo "${result[@]}"

в словах: если мы еще не видели данного слова, Добавьте его к результату массив и флаг его, как это было видно. Как только слово было замечено, игнорируйте последующие появления этого.

0
27.01.2020, 20:09

Вы используете ZSH:

$ array=(1 2 3 2 1)
$ echo ${(u)array[@]}
1 2 3

или (если ksh_Arrays опция не установлена) Даже

$ echo ${(u)array}
1 2 3
9
27.01.2020, 20:09

Для массива с произвольными значениями это довольно хитро с удар , поскольку это не имеет встроенного оператора для этого.

удар однако, оказывается, не поддерживает символы NUL хранения в своих переменных, таким образом, можно использовать это для передачи этого другим командам:

эквивалент zsh:

new_array=("${(@u}array}")

в недавней системе GNU, мог быть:

eval "new_array=($(
  printf "%s\0" "${array[@]}" |
    LC_ALL=C sort -zu |
    xargs -r0 bash -c 'printf "%q\n" "$@"' sh
  ))"

, С другой стороны, с последними версиями удар , и принятие ни один из элементов массива не пуст, вы могли использовать ассоциативные массивы:

unset hash
typeset -A hash
for i in "${array[@]}"; do
  hash[$i]=
done
new_array=("${!hash[@]}")

С ударом 4.4 и более новый и с видом GNU :

readarray -td '' new_array < <(
  printf '%s\0' "${array[@]}" | LC_ALL=C sort -zu)

порядок элементов не был бы тем же в тех различных решениях.

С tcsh:

set -f new_array = ($array:q)

сохранил бы элемент f irst ( b => b) как zsh (u) флаг расширения.

set -l new_array = ($array:q)

сохранил бы последнее ( b => b ). Они однако удаляют пустые элементы из массива.

4
27.01.2020, 20:09

Теги

Похожие вопросы