Правильный способ - использовать следующее в вашем ~ / .bashrc
, как @Gilles предложил выше (здесь более короткая версия):
_my_cd () { CDPATH= _cd "$@";}
Лучше всего проверить CDPATH
тогда и только тогда, когда нет совпадения обнаруживаются локально:
_my_cd () { CDPATH= _cd "$@"; if [ -z "$COMPREPLY" ]; then _cd "$@"; fi;}
Таким образом, вы получаете функциональность программируемого завершения, не доставляя неудобств. Не забывайте
complete -F _my_cd cd
По какой-то причине / usr / share / bash-Completion / bash_completion
имеет -o nospace
для cd
(хотя nospace
кажется по умолчанию), так что вы также можете иметь:
complete -F _my_cd -o nospace cd
Как правило, аргумент автоматически преобразуется в целое число, если он используется внутри арифметического $((...))
расширения. Этот цикл суммирует все аргументы:
for x; do sum=$((sum+x)); done; echo "$sum"
Оболочка кэширует все аргументы в отдельных ячейках памяти, поскольку программа на языке C работает с массивом argv[]. Пользователю оболочки не нужно иметь дело непосредственно с этим массивом, оболочка помогает, назначая их $1, $2, $3 и т. д. Оболочка также абстрагирует такой список как «$@». И, наконец, синтаксис for x
является сокращением для for x in "$@"
для перебора всех аргументов.
Предполагается, что аргументы представляют собой десятичные числа, которые не начинаются с нуля, восьмеричные числа, начинающиеся с нуля, или шестнадцатеричные числа, начинающиеся с 0x
, и что общая сумма не переполняется (2^63 -1 в 64-битных системах)
Этот список:
$./script 12 021 0xab
Напечатает200
(десятичный результат ).
Возьмите аргументы один за другим:
total=0
while [ -n "$1" ]; do
total=$((total + "$1"))
shift
done
Или используйте цикл for
:
total=0
for argument; do
total=$((total + "$argument"))
done
Этого можно добиться следующим:
tr ' ' '+' <<<"$@" | bc
Он принимает все переданные аргументы и заменяет пробел знаком +
, а затем передает это в bc
.
Помимо $(())
, как и в других ответах, вы также можете использовать (())
и использовать +=
внутри, как это:
sum=0
for x; do
(( sum += x ))
done
echo $sum
Также может быть полезно объяснить, что вы делали в предоставленном вами коде. По сути, вы разделяете каждый аргумент на пробел (, потому что вы не удваиваете -кавычки $@
в for i in $@
), а затем вы перебираете результат. Затем вы проигнорировали выполненное вами присваивание и снова дважды разделили аргументы по пробелам и соединили последний аргумент первого набора и первый аргумент второго набора с помощью +
, затем вызвали команду, названную первым аргументом, с помощью остальные аргументы как аргументы. Так, например, если бы этот скрипт был назван sum
и вы назвали его так :sum "1 2" 3
, этот $@+$@
попытался бы вызвать команду 1
(, даже ища/bin/1
)вот так:1 "2" "3+1" "2" "3"
. Это, вероятно, привело бы к предупреждению bash что-то вроде bash: 1: command not found
, 3 раза (по одному разу для каждого аргумента ). Затем, поскольку вы написали echo
внутри цикла, он попытается сообщить общее количество раз для каждого аргумента. На самом деле, он попытается выполнить 1 "2" "3"
, а 1
снова интерпретируется как команда из-за обратных кавычек в строке. Это также приведет к предупреждению bash о том, что команда не найдена. Поскольку команды не было, вывода не будет, а echo
просто выведет «итого».Таким образом, полный результат:
$ sum "1 2" 3
bash: 1: command not found
bash: 1: command not found
the total is
bash: 1: command not found
bash: 1: command not found
the total is
bash: 1: command not found
bash: 1: command not found
the total is
#!/bin/sh
IFS='+'
printf '%s\n' "$*" | bc
Тестирование
$./script.sh 1 2 3 -1 30 0.1
35.1
"$*"
расширит до позиционных параметров (аргументы командной строки ), разделенные первым символом переменной оболочки IFS
. Мы устанавливаем для IFS
знак плюс и передаем строку в bc
для оценки.
Если требуется только целочисленная арифметика:
#!/bin/sh
IFS='+'
printf '%d\n' "$(( $* ))"