Просто извлечение содержания архива не установит Ваше программное обеспечение. Проверьте папку, где Вы извлекли файлы, там будут инструкции по установке.
Можно также попытаться после этого руководства создать debian пакет из архива tar.gz.
Наконец, jdk1.7 находится в "экспериментальном" репозитории Debian. Можно отредактировать /etc/apt/sources.lst
включать эту строку:
deb http://ftp.debian.org/debian experimental main
Затем выполните эти команды:
sudo apt-get update
sudo apt-get install default-jdk
ПРЕДУПРЕЖДЕНИЕ: В зависимости от того, насколько актуальный Ваша система, много пакетов, возможно, должны были бы быть обновлены, который мог привести к нестабильной системе. Удостоверьтесь, что Вы изменяете Ваш /etc/apt/sources.lst
назад к тому, как это было прежде при выборе этого метода.
В bash
вы можете использовать $ {! Varname}
для расширения переменной, на которую ссылается содержимое другой переменной. Например:
$ var=hello
$ foo () { echo "${!1}"; }
$ foo var
hello
На странице руководства:
${!prefix*}
${!prefix@}
Names matching prefix. Expands to the names of variables whose names
begin with prefix, separated by the first character of the IFS special
variable. When @ is used and the expansion appears within double quotes,
each variable name expands to a separate word.
Кроме того, чтобы установить переменную, на которую ссылается содержимое (без опасностей eval
), вы можете использовать declare
. Например:
$ var=target
$ declare "$var=hello"
$ echo "$target"
hello
Таким образом, вы можете написать свою функцию так (будьте осторожны, потому что если вы используете declare
в функции, вы должны указать -g
, иначе переменная будет локальной) :
shopt -s extglob
assign()
{
target=$1
bigstr=${!1}
substr=$2
if [ -z "$bigstr" ]; then
declare -g -- "$target=$substr"
elif [[ $bigstr != @(|*:)$substr@(|:*) ]]; then
declare -g -- "$target=$bigstr:$substr"
fi
}
И используйте это как:
assign PATH /path/to/binaries
Обратите внимание, что я также исправил ошибку, когда if substr
уже является подстрокой одного из разделенных двоеточием членов bigstr
, но не его собственный член, тогда он не будет добавлен. Например, это позволит добавить / bin
к переменной PATH
, уже содержащей / usr / bin
. Он использует наборы extglob
для сопоставления либо начала / конца строки, либо двоеточия, а затем чего-либо еще. Без extglob
альтернативой будет:
[[ $bigstr != $substr && $bigstr != *:$substr &&
$bigstr != $substr:* && $bigstr != *:$substr:* ]]
Новым в bash 4.3 является опция -n
для объявления
& local
:
func() {
local -n ref="$1"
ref="hello, world"
}
var='goodbye world'
func var
echo "$var"
Это распечатывает привет, мир
.
С помощью нескольких трюков вы можете фактически передать именованные параметры в функции, наряду с массивами (тестировались на bash 3 и 4).
Метод, который я разработал, позволяет получить доступ к параметрам, передаваемым в такую функцию:
testPassingParams() {
@var hello
l=4 @array anArrayWithFourElements
l=2 @array anotherArrayWithTwo
@var anotherSingle
@reference table # references only work in bash >=4.3
@params anArrayOfVariedSize
test "$hello" = "$1" && echo correct
#
test "${anArrayWithFourElements[0]}" = "$2" && echo correct
test "${anArrayWithFourElements[1]}" = "$3" && echo correct
test "${anArrayWithFourElements[2]}" = "$4" && echo correct
# etc...
#
test "${anotherArrayWithTwo[0]}" = "$6" && echo correct
test "${anotherArrayWithTwo[1]}" = "$7" && echo correct
#
test "$anotherSingle" = "$8" && echo correct
#
test "${table[test]}" = "works"
table[inside]="adding a new value"
#
# I'm using * just in this example:
test "${anArrayOfVariedSize[*]}" = "${*:10}" && echo correct
}
fourElements=( a1 a2 "a3 with spaces" a4 )
twoElements=( b1 b2 )
declare -A assocArray
assocArray[test]="works"
testPassingParams "first" "${fourElements[@]}" "${twoElements[@]}" "single with spaces" assocArray "and more... " "even more..."
test "${assocArray[inside]}" = "adding a new value"
Другими словами, вы можете не только вызывать свои параметры по их именам (что составляет более читабельное ядро), но и фактически передавать массивы (а ссылки на переменные - эта функция работает только в bash 4.3)! Кроме того, все отображенные переменные находятся в локальной области видимости, всего $1 (и другие).
Код, который делает эту работу довольно легкой и работает как на bash 3, так и на bash 4 (это единственные версии, с которыми я его тестировал). Если вас интересуют такие трюки, как этот, которые делают разработку с bash намного приятнее и проще, вы можете взглянуть на мою Bash Infinity Framework, код ниже был разработан для этой цели.
Function.AssignParamLocally() {
local commandWithArgs=( $1 )
local command="${commandWithArgs[0]}"
shift
if [[ "$command" == "trap" || "$command" == "l="* || "$command" == "_type="* ]]
then
paramNo+=-1
return 0
fi
if [[ "$command" != "local" ]]
then
assignNormalCodeStarted=true
fi
local varDeclaration="${commandWithArgs[1]}"
if [[ $varDeclaration == '-n' ]]
then
varDeclaration="${commandWithArgs[2]}"
fi
local varName="${varDeclaration%%=*}"
# var value is only important if making an object later on from it
local varValue="${varDeclaration#*=}"
if [[ ! -z $assignVarType ]]
then
local previousParamNo=$(expr $paramNo - 1)
if [[ "$assignVarType" == "array" ]]
then
# passing array:
execute="$assignVarName=( \"\${@:$previousParamNo:$assignArrLength}\" )"
eval "$execute"
paramNo+=$(expr $assignArrLength - 1)
unset assignArrLength
elif [[ "$assignVarType" == "params" ]]
then
execute="$assignVarName=( \"\${@:$previousParamNo}\" )"
eval "$execute"
elif [[ "$assignVarType" == "reference" ]]
then
execute="$assignVarName=\"\$$previousParamNo\""
eval "$execute"
elif [[ ! -z "${!previousParamNo}" ]]
then
execute="$assignVarName=\"\$$previousParamNo\""
eval "$execute"
fi
fi
assignVarType="$__capture_type"
assignVarName="$varName"
assignArrLength="$__capture_arrLength"
}
Function.CaptureParams() {
__capture_type="$_type"
__capture_arrLength="$l"
}
alias @trapAssign='Function.CaptureParams; trap "declare -i \"paramNo+=1\"; Function.AssignParamLocally \"\$BASH_COMMAND\" \"\$@\"; [[ \$assignNormalCodeStarted = true ]] && trap - DEBUG && unset assignVarType && unset assignVarName && unset assignNormalCodeStarted && unset paramNo" DEBUG; '
alias @param='@trapAssign local'
alias @reference='_type=reference @trapAssign local -n'
alias @var='_type=var @param'
alias @params='_type=params @param'
alias @array='_type=array @param'
Именованные аргументы просто не так, как был разработан синтаксис Bash. Bash был разработан как итеративное усовершенствование оболочки Bourne. Таким образом, он должен гарантировать, что определенные вещи работают между двумя оболочками в максимально возможной степени. Таким образом, не означает, что упрощает создание сценариев в целом, это просто должно быть лучше, чем Bourne, при этом гарантируя, что если вы возьмете сценарий из среды Bourne на bash
, он как можно проще. Это нетривиально, поскольку многие оболочки все еще рассматривают Борна как стандарт де-факто. Поскольку люди пишут свои сценарии так, чтобы они были совместимы с Борном (для этой переносимости), необходимость остается в силе и вряд ли когда-нибудь изменится.
Вам, вероятно, лучше полностью взглянуть на другой сценарий оболочки (например, python
или что-то в этом роде), если это вообще возможно. Если вы сталкиваетесь с языковыми ограничениями, вам нужно начать использовать новый язык.
assign ()
{
if [ -z ${!1} ]; then
eval $1=$2
else
if [[ ${!1} != *$2* ]]; then
eval $1=${!1}:$2
fi
fi
}
$ echo =$x=
==
$ assign x y
$ echo =$x=
=y=
$ assign x y
$ echo =$x=
=y=
$ assign x z
$ echo =$x=
=y:z=
Подходит ли это?
Вы можете использовать eval
для установки параметра. Описание этой команды можно найти здесь. Следующее использование eval
является неправильным:
wrong(){ eval $1=$2 }
Что касается дополнительной оценки eval
делает, вы должны использовать
assign(){ eval $1='$2' }
Проверьте результаты использования этих функций:
$ X1='$X2' $ X2='$X3' $ X3='xxx' $ $ echo :$X1: :$X2: $ echo :$X2: :$X3: $ echo :$X3: :xxx: $ $ wrong Y $X1 $ echo :$Y: :$X3: $ $ assign Y $X1 $ echo :$Y: :$X2: $ $ assign Y "hallo world" $echo :$Y: :hallo world: $ # the following may be unexpected $ assign Z $Y $ echo ":$Z:" :hallo: $ # so you have to quote the second argument if its a variable $ assign Z "$Y" $ echo ":$Z:" :hallo world:
Но вы можете достичь своей цели без использования eval
. Я предпочитаю этот способ, который более прост.
Следующая функция делает подстановку правильным способом (я надеюсь)
augment(){ local CURRENT=$1 local AUGMENT=$2 local NEW if [[ -z $CURRENT ]]; then NEW=$AUGMENT elif [[ ! ( ( $CURRENT = $AUGMENT ) || ( $CURRENT = $AUGMENT:* ) || \ ( $CURRENT = *:$AUGMENT ) || ( $CURRENT = *:$AUGMENT:* ) ) ]]; then NEW=$CURRENT:$AUGMENT else NEW=$CURRENT fi echo "$NEW" }
Проверьте следующий результат
augment /usr/bin /bin /usr/bin:/bin augment /usr/bin:/bin /bin /usr/bin:/bin augment /usr/bin:/bin:/usr/local/bin /bin /usr/bin:/bin:/usr/local/bin augment /bin:/usr/bin /bin /bin:/usr/bin augment /bin /bin /bin augment /usr/bin: /bin /usr/bin::/bin augment /usr/bin:/bin: /bin /usr/bin:/bin: augment /usr/bin:/bin:/usr/local/bin: /bin /usr/bin:/bin:/usr/local/bin: augment /bin:/usr/bin: /bin /bin:/usr/bin: augment /bin: /bin /bin: augment : /bin ::/bin augment "/usr lib" "/usr bin" /usr lib:/usr bin augment "/usr lib:/usr bin" "/usr bin" /usr lib:/usr bin
Теперь вы можете использовать функцию augment
следующим образом, чтобы установить переменную:
PATH=`augment PATH /bin` CLASSPATH=`augment CLASSPATH /bin` LD_LIBRARY_PATH=`augment LD_LIBRARY_PATH /usr/lib`
Это делается очень просто, и bash
вообще не требуется - это базовое поведение присвоения через расширение параметра, определенное POSIX:
: ${PATH:=this is only assigned to \$PATH if \$PATH is null or unset}
Для демонстрации аналогично @Graeme, но в переносимом виде:
_fn() { echo "$1 ${2:-"$1"} $str" ; }
% str= ; _fn "${str:=hello}"
> hello hello hello
И там я делаю str=
только для того, чтобы убедиться, что он имеет нулевое значение, потому что расширение параметра имеет встроенную защиту от переназначения окружения оболочки в строке, если оно уже установлено.
Для вашей конкретной проблемы я не считаю, что именованные аргументы необходимы, хотя они, конечно, возможны. Используйте $IFS
вместо этого:
assign() { oFS=$IFS ; IFS=: ; add=$*
set -- $PATH ; for p in $add ; do {
for d ; do [ -z "${d%"$p"}" ] && break
done ; } || set -- $* $p ; done
PATH= ; echo "${PATH:="$*"}" ; IFS=$oFS
}
Вот что получается при запуске:
% PATH=/usr/bin:/usr/yes/bin
% assign \
/usr/bin \
/usr/yes/bin \
/usr/nope/bin \
/usr/bin \
/nope/usr/bin \
/usr/nope/bin
> /usr/bin:/usr/yes/bin:/usr/nope/bin:/nope/usr/bin
% echo "$PATH"
> /usr/bin:/usr/yes/bin:/usr/nope/bin:/nope/usr/bin
% dir="/some crazy/dir"
% p=`assign /usr/bin /usr/bin/new "$dir"`
% echo "$p" ; echo "$PATH"
> /usr/bin:/usr/yes/bin:/usr/nope/bin:/nope/usr/bin:/some crazy/dir:/usr/bin/new
> /usr/bin:/usr/yes/bin:/usr/nope/bin:/nope/usr/bin:/some crazy/dir:/usr/bin/new
Заметили, что он добавил только те аргументы, которых еще не было в $PATH
или которые были раньше? Или даже то, что он вообще принял более одного аргумента? $IFS
- это удобно.
Со стандартным синтаксисом sh
(будет работать в bash
, а не только в bash
]), вы можете сделать:
assign() {
eval '
case :${'"$1"'}: in
(::) '"$1"'=$2;; # was empty, copy
(*:"$2":*) ;; # already there, do nothing
(*) '"$1"'=$1:$2;; # otherwise, append with a :
esac'
}
Как и для решений, использующих bash
declare
, это безопасно , если $ 1
содержит допустимое имя переменной.
Я не могу найти ничего похожего на ruby, python и т. д., но мне кажется, что это ближе
foo() {
BAR="$1"; BAZ="$2"; QUUX="$3"; CORGE="$4"
...
}
На мой взгляд, читабельность лучше, 4 строки избыточны для объявления имен ваших параметров. Выглядит ближе к современным языкам.