我的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&T 的 4.4 和更高版本的实现ksh
)zsh
)bash
。请注意,
IFS=: read A B <<< "$1"
它有几个问题:-r
这意味着反斜杠将进行一些特殊处理。[::1]:443
为[
and:1]:443
而不是[
and 空字符串(您需要IFS=: read -r A B rest_ignored
或[::1]
and443
(您不能使用该方法)-d ''
inzsh
orbash
并且数据不包含 NUL 字符,但请注意 herestrings(或 heredocs)确实添加了一个额外的换行符!)zsh
(语法来自哪里)和bash
,这里的字符串是使用临时文件实现的,因此它通常比使用${x#y}
或 split+glob 运算符效率低。:
只需在单独的语句中删除;另外,从输入中删除 $host 以获取端口:另一个想法:
here 字符串只是单行 here 文档的语法快捷方式。