Meu dash
script usa um parâmetro na forma de hostname:port
, ou seja:
myhost:1234
Considerando que a porta é opcional, ou seja:
myhost
Eu preciso ler o host e a porta em variáveis separadas. No primeiro caso, eu posso fazer:
HOST=${1%%:*}
PORT=${1##*:}
Mas isso não funciona no segundo caso, quando a porta foi omitida; echo ${1##*:}
simplesmente retorna o nome do host, em vez de uma string vazia.
No Bash, eu poderia fazer:
IFS=: read A B <<< asdf:111
Mas isso não funciona dash
.
Posso dividir corda no :
no traço, sem invocar programas externos ( awk
, tr
, etc.)?
%%
torna ganancioso (ao contrário de%
), então ele realmente faz isso, pelo menos em parte; não iria funcionar##
.Respostas:
Apenas faça:
Você pode alterar
case $1
paracase ${1##*[]]}
para contabilizar valores de$1
like[::1]
(um endereço IPv6 sem parte da porta ).Para dividir, você pode usar o operador split + glob (deixe uma expansão de parâmetro sem aspas), pois é para isso que serve:
(embora isso não permita nomes de host que contenham dois pontos (como no endereço IPv6 acima)).
Esse operador split + glob atrapalha e causa tanto dano o resto do tempo que parece justo que seja usado sempre que necessário (porém, eu concordo que é muito complicado de usar, especialmente considerando que o POSIX
sh
não tem suporte para escopo local, nem para variáveis ($IFS
aqui) nem para opções (noglob
aqui) (emboraash
e derivados gostodash
são algumas das que fazer (em conjunto com a AT & T implementaçõesksh
,zsh
ebash
4.4 e acima)).Observe que ele
IFS=: read A B <<< "$1"
possui alguns problemas:-r
que significa que a barra invertida passará por um processamento especial.[::1]:443
em[
e em:1]:443
vez de[
e a cadeia vazia (da qual você precisariaIFS=: read -r A B rest_ignored
ou[::1]
e443
(da qual você não pode usar essa abordagem)-d ''
emzsh
oubash
e os dados não contém caracteres NUL, mas, em seguida, note que herestrings (ou heredocs) não adicionar um caractere de nova linha extra!)zsh
(de onde vem a sintaxe) ebash
, aqui, as strings são implementadas usando arquivos temporários; portanto, geralmente é menos eficiente do que usar${x#y}
ou dividir + operadores glob.fonte
Basta remover o
:
em uma declaração separada; Além disso, remova $ host da entrada para obter a porta:fonte
Outro pensamento:
fonte
Uma string here é apenas um atalho sintático para um documento aqui de linha única.
fonte