Можно всегда использовать функцию:
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
) или не выбирая правильное имя.
удара С 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
Это решение работало для меня.
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
Чтобы сделать это полностью в оболочке и поместить результат в массиве,
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[@]}"
в словах: если мы еще не видели данного слова,
Добавьте его к результату
массив и флаг его, как это было видно.
Как только слово было замечено, игнорируйте последующие появления этого.
Вы используете ZSH:
$ array=(1 2 3 2 1)
$ echo ${(u)array[@]}
1 2 3
или (если ksh_Arrays
опция не установлена) Даже
$ echo ${(u)array}
1 2 3
Для массива с произвольными значениями это довольно хитро с удар
, поскольку это не имеет встроенного оператора для этого.
удар
однако, оказывается, не поддерживает символы 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
). Они однако удаляют пустые элементы из массива.