Я даю сильно сфокусированный на Bash ответ из-за тега bash
.
Пока вы имеете дело только с именованными переменными в Bash, эта функция всегда должна сообщать вам, установлена ли переменная, даже если это пустой массив.
is-variable-set() {
declare -p $1 &>dev/null
}
В Bash (по крайней мере, начиная с 3.0), если var
является объявленной / установленной переменной, то declare -p var
выводит команду declare
, которая бы установите переменную var
равной ее текущему типу и значению и возвращает код состояния 0
(успех). Если var
не объявлено, то declare -p var
выводит сообщение об ошибке в stderr
и возвращает код состояния 1
. Используя &>/dev/null
, перенаправляет как обычный вывод stdout
, так и stderr
на /dev/null
, чтобы его никогда не было видно, и без изменения кода состояния. Таким образом, функция возвращает только код состояния.
[ -n "$var" ]
: Эта проверка только, если${var[0]}
не пусто. (В Bash$var
совпадает с${var[0]}
.)[ -n "${var+x}" ]
: Это только проверяет, установлено ли${var[0]}
.[ "${#var[@]}" != 0 ]
: Проверяется только, установлен ли хотя бы один индекс$var
.
Это работает только для именованных переменных (включая Я даю сильно сфокусированный на Bash ответ из-за тега [114]. Пока вы имеете дело только с именованными переменными в Bash, эта функция всегда должна сообщать вам, установлена ли переменная, даже если это пустой массив. В Bash (по крайней мере, начиная с 3.0), если [115] является объявленной / установленной переменной, то [116] выводит команду [117], которая бы установите переменную [118] равной ее текущему типу и значению и возвращает код состояния [119] (успех). Если [1110] не объявлено, то [1111] выводит сообщение об ошибке в [1112] и возвращает код состояния [1113]. Используя [1114], перенаправляет как обычный вывод [1115], так и [1116] на [1117], чтобы его никогда не было видно, и без изменения кода состояния. Таким образом, функция возвращает только код состояния. Это работает только для именованных переменных (включая [1126]), а не определенных специальных переменных ( Если в вашем скрипте есть массивы, и вы пытаетесь сделать его совместимым с максимально возможным количеством оболочек, рассмотрите возможность использования Если вам нужен ваш сценарий для совместимости с POSIX sh, вы не можете использовать массивы. Без массивов Эта функция сбрасывает переменную Я пропускаю Обратите внимание, что результаты теста могут быть неожиданными из-за того, что Bash рассматривает индексы нечислового массива как «0», если переменная не была объявлена как ассоциативный массив. Кроме того, ассоциативные массивы действительны только в Bash 4.0 +. Тестовая мнемоника в строке заголовка соответствует
), а не определенных специальных переменных ( Заметка
Короткий ответ
Почему это работает
Почему другие методы (иногда) терпят неудачу в Bash
Когда этот метод не работает в Bash
$!
, $@
, $#
, $
, $*
, $?
, $-
, [1134]
, $1
, $2
, ... и все, что я мог забыть). Поскольку ни один из них не является массивом, стиль POSIX [ -n "${var+x}" ]
работает для всех этих специальных переменных. Но остерегайтесь оборачивать его в функцию, так как многие специальные переменные меняют значения / существование при вызове функций. Замечание по совместимости оболочки
typeset -p
вместо declare -p
. Я читал, что ksh поддерживает только первое, но не смог проверить это. Я знаю, что Bash 3.0+ и Zsh 5.5.1 поддерживают оба typeset -p
и declare -p
, отличающиеся только тем, что одно является альтернативой другому. Но я не проверял различия между этими двумя ключевыми словами и не проверял другие оболочки. [ -n "{$var+x}" ]
работает. Код сравнения для различных методов в Bash
var
, eval
переданный код, запускает тесты, чтобы определить, установлено ли var
кодом eval
d, и, наконец, показывает результирующие коды состояния для различных тестов. test -v var
, [ -v var ]
и [[ -v var ]]
, потому что они дают результаты, идентичные стандарту POSIX [ -n "${var+x}" ]
, при этом требуется Bash 4.2+. Я также пропускаю typeset -p
, потому что он совпадает с declare -p
в оболочках, которые я тестировал (Bash 3.0 через 5.0 и Zsh 5.5.1). is-var-set-after() {
# Set var by passed expression.
unset var
eval "$1"
# Run the tests, in increasing order of accuracy.
[ -n "$var" ] # (index 0 of) var is nonempty
nonempty=$?
[ -n "${var+x}" ] # (index 0 of) var is set, maybe empty
plus=$?
[ "${#var[@]}" != 0 ] # var has at least one index set, maybe empty
count=$?
declare -p var &>/dev/null # var has been declared (any type)
declared=$?
# Show test results.
printf '%30s: %2s %2s %2s %2s\n' "$1" $nonempty $plus $count $declared
}
Код тестового примера
# Header.
printf '%30s: %2s %2s %2s %2s\n' "test" '-n' '+x' '#@' '-p'
# First 5 tests: Equivalent to setting 'var=foo' because index 0 of an
# indexed array is also the nonindexed value, and non-numerical
# indices in an array not declared as associative are the same as
# index 0.
is-var-set-after "var=foo" # 0 0 0 0
is-var-set-after "var=(foo)" # 0 0 0 0
is-var-set-after "var=([0]=foo)" # 0 0 0 0
is-var-set-after "var=([x]=foo)" # 0 0 0 0
is-var-set-after "var=([y]=bar [x]=foo)" # 0 0 0 0
# '[ -n "$var" ]' fails when var is empty.
is-var-set-after "var=''" # 1 0 0 0
is-var-set-after "var=([0]='')" # 1 0 0 0
# Indices other than 0 are not detected by '[ -n "$var" ]' or by
# '[ -n "${var+x}" ]'.
is-var-set-after "var=([1]='')" # 1 1 0 0
is-var-set-after "var=([1]=foo)" # 1 1 0 0
is-var-set-after "declare -A var; var=([x]=foo)" # 1 1 0 0
# Empty arrays are only detected by 'declare -p'.
is-var-set-after "var=()" # 1 1 1 0
is-var-set-after "declare -a var" # 1 1 1 0
is-var-set-after "declare -A var" # 1 1 1 0
# If 'var' is unset, then it even fails the 'declare -p var' test.
is-var-set-after "unset var" # 1 1 1 1
Тестовый вывод
[ -n "$var" ]
, [ -n "${var+x}" ]
, [ "${#var[@]}" != 0 ]
и declare -p var
, соответственно. test: -n +x #@ -p
var=foo: 0 0 0 0
var=(foo): 0 0 0 0
var=([0]=foo): 0 0 0 0
var=([x]=foo): 0 0 0 0
var=([y]=bar [x]=foo): 0 0 0 0
var='': 1 0 0 0
var=([0]=''): 1 0 0 0
var=([1]=''): 1 1 0 0
var=([1]=foo): 1 1 0 0
declare -A var; var=([x]=foo): 1 1 0 0
var=(): 1 1 1 0
declare -a var: 1 1 1 0
declare -A var: 1 1 1 0
unset var: 1 1 1 1
Резюме
declare -p var &>/dev/null
надежно (100%?) Для тестирования именованных переменных в Bash, начиная с версии 3.0. [ -n "${var+x}" ]
надежен в ситуациях, соответствующих POSIX, но не может обрабатывать массивы. $!
, $@
, $#
, $
, $*
, $?
, $-
, [1134]
, $1
, $2
, ... и все, что я мог забыть). Поскольку ни один из них не является массивом, стиль POSIX [ -n "${var+x}" ]
работает для всех этих специальных переменных. Но остерегайтесь оборачивать его в функцию, так как многие специальные переменные меняют значения / существование при вызове функций.
Если в вашем скрипте есть массивы, и вы пытаетесь сделать его совместимым с максимально возможным количеством оболочек, рассмотрите возможность использования typeset -p
вместо declare -p
. Я читал, что ksh поддерживает только первое, но не смог проверить это. Я знаю, что Bash 3.0+ и Zsh 5.5.1 поддерживают оба typeset -p
и declare -p
, отличающиеся только тем, что одно является альтернативой другому. Но я не проверял различия между этими двумя ключевыми словами и не проверял другие оболочки.
Если вам нужен ваш сценарий для совместимости с POSIX sh, вы не можете использовать массивы. Без массивов [ -n "{$var+x}" ]
работает.
Эта функция сбрасывает переменную var
, eval
переданный код, запускает тесты, чтобы определить, установлено ли var
кодом eval
d, и, наконец, показывает результирующие коды состояния для различных тестов.
Я пропускаю test -v var
, [ -v var ]
и [[ -v var ]]
, потому что они дают результаты, идентичные стандарту POSIX [ -n "${var+x}" ]
, при этом требуется Bash 4.2+. Я также пропускаю typeset -p
, потому что он совпадает с declare -p
в оболочках, которые я тестировал (Bash 3.0 через 5.0 и Zsh 5.5.1).
Обратите внимание, что результаты теста могут быть неожиданными из-за того, что Bash рассматривает индексы нечислового массива как «0», если переменная не была объявлена как ассоциативный массив. Кроме того, ассоциативные массивы действительны только в Bash 4.0 +.
[112] Тестовая мнемоника в строке заголовка соответствует [ -n "$var" ]
, [ -n "${var+x}" ]
, [ "${#var[@]}" != 0 ]
и declare -p var
, соответственно.
declare -p var &>/dev/null
надежно (100%?) Для тестирования именованных переменных в Bash, начиная с версии 3.0.[ -n "${var+x}" ]
надежен в ситуациях, соответствующих POSIX, но не может обрабатывать массивы.- Существуют другие тесты для проверки, является ли переменная непустой, и для проверки объявленных переменных в других оболочках. Но эти тесты не подходят ни для скриптов Bash, ни для POSIX.
Я думаю, что OP имеет в виду наличие нескольких интерфейсов, настроенных на тестовой машине.
Вы можете указать IP-адрес, с которым будет связываться Django, следующим образом:
# python manage.py runserver 0.0.0.0:8000
Это будет связывать Django ко всем интерфейсам на порту 8000. Вы можете передать любой активный IP-адрес вместо 0.0.0.0, поэтому просто используйте IP-адрес интерфейса, к которому вы хотите подключиться.
Надеюсь, это поможет.
Да, если IP-адрес вашего интерфейса, например, 192.168.1.2, и вы хотите работать на порту 8080, запустите сервер разработки следующим образом:
./manage.py runserver 192.168.1.2:8080
Нет. Это не так, как это работает. Интерфейс имеет IP-адрес, у вас есть сеть с тестовым сервером и вашим ПК. Вы должны подключиться к этому IP (возможно, с альтернативным портом, который вы указали), и все. Если у вас есть только эти два устройства в сети, наиболее вероятно, что оба они должны иметь статические IP-адреса. (или, если нет общей сети, вы не можете подключиться друг к другу).