Мой dash
скрипт принимает параметр в виде hostname:port
, то есть:
myhost:1234
Принимая во внимание, что порт является необязательным, то есть:
myhost
Мне нужно прочитать хост и порт в отдельных переменных. В первом случае я могу сделать:
HOST=${1%%:*}
PORT=${1##*:}
Но это не работает во втором случае, когда порт был опущен; echo ${1##*:}
просто возвращает имя хоста вместо пустой строки.
В Bash я мог бы сделать:
IFS=: read A B <<< asdf:111
Но это не работает в dash
.
Можно ли разбить строку на :
тире, не вызывая внешние программы ( awk
, tr
и т. Д.)?
%%
делает его жадным (в отличие от%
), поэтому он действительно делает это, по крайней мере, частично; это не будет работать с##
.Ответы:
Просто делать:
Возможно, вы захотите изменить на,
case $1
чтобыcase ${1##*[]]}
учесть значения$1
like[::1]
(адрес IPv6 без части порта ).Чтобы разделить, вы можете использовать оператор split + glob (оставить расширение параметра без кавычек), так как для этого он и нужен:
(хотя это не позволит использовать имена хостов, содержащие двоеточие (как для этого адреса IPv6 выше)).
Этот оператор split + glob мешает и причиняет столько вреда в остальное время, что было бы совершенно справедливо использовать его всякий раз, когда это необходимо (хотя, я согласен, его очень громоздко использовать, особенно учитывая, что POSIX
sh
не имеет поддержка локальной области видимости, ни для переменных ($IFS
здесь), ни для опций (noglob
здесь) (хотяash
иdash
некоторые производные, такие как (вместе с реализациями AT & Tksh
,zsh
иbash
4.4 и выше)).Обратите внимание, что
IFS=: read A B <<< "$1"
есть несколько собственных проблем:-r
что означает, что обратная косая черта подвергнется специальной обработке.[::1]:443
на[
и:1]:443
вместо того , чтобы[
и пустую строку (для которой вам нужноIFS=: read -r A B rest_ignored
или[::1]
и443
(для которых вы не можете использовать этот подход)-d ''
вzsh
илиbash
данные не содержат NUL-символов, но затем обратите внимание, что здесь-строки (или heredocs) действительно добавляют дополнительный символ новой строки!)zsh
(откуда исходит синтаксис) иbash
здесь строки реализуются с использованием временных файлов, поэтому обычно они менее эффективны, чем использование${x#y}
операторов split или glob.источник
Просто удалите
:
в отдельном заявлении; также удалите $ host из ввода, чтобы получить порт:источник
Еще одна мысль:
источник
Строка here - это всего лишь синтаксический ярлык для однострочного документа здесь.
источник