私のdash
スクリプトは次の形式のパラメータを使用しますhostname:port
。
myhost:1234
ポートはオプションです。つまり、次のようになります。
myhost
ホストとポートを別々の変数として読み取る必要があります。最初のケースでは、次のようにすることができます。
HOST=${1%%:*}
PORT=${1##*:}
ただし、2番目のケースでは、ポートが省略された場合は機能せず、空の文字列ではecho ${1##*:}
なくホスト名のみが返されます。
Bashでは、次のことができます。
IFS=: read A B <<< asdf:111
しかし、ここではdash
。
外部プログラム(など):
を呼び出さずに文字列をダッシュに分割できますか?awk
tr
答え1
ただし:
case $1 in
(*:*) host=${1%:*} port=${1##*:};;
(*) host=$1 port=$default_port;;
esac
同様の値を考慮してcase $1
変更する必要があるかもしれません(case ${1##*[]]}
$1
[::1]
ポート部分)。
分割するには、次のものを使用できます。分割+グローバル演算子(引用符なしでパラメータ拡張を残してください)、これはまさにその用途です。
set -o noglob # disable glob part
IFS=: # split on colon
set -- $1 # split+glob
host=$1 port=${2:-$default_port}
(ただし、ホスト名にコロン(上記のIPv6アドレスなど)を含めることはできません。)
Split+Glob演算子が邪魔になり、多くのダメージを与えます。残りの時間には必要なだけ使用することが公平に見えます。 (しかし、POSIXが変数(ここ)またはオプションの両方がローカルスコープをサポートしていないことを考慮すると、使用するのは非常に面倒であることsh
に同意します。)$IFS
(noglob
this)&T実装も含む))。ash
dash
ksh
zsh
bash
それ自体IFS=: read A B <<< "$1"
にいくつかの問題があることに注意してください。
-r
これはバックスラッシュが特別な処理を経なければならないことを忘れています。[::1]:443
それはandの[
代わりに:1]:443
空[
の文字列に分割されます(これにはIFS=: read -r A B rest_ignored
or[::1]
andが必要です443
(これにはその方法は使用できません)。- 改行が最初に発生した後のすべての項目を削除するため、任意の文字列では機能しません(または内で使用せず、
-d ''
データzsh
にbash
NUL文字が含まれていない場合)。ただし、herestrings(またはheredocs)は追加の文字列を追加します。改行文字!) zsh
(文法ソース)と でbash
文字列は一時ファイルを使用して実装されているため、通常${x#y}
または分割+glob演算子を使用するよりも効率が悪くなります。
答え2
:
別の文から削除してポートを取得するには、入力から$ hostを削除します。
host=${1%:*}
port=${1#"$host"}
port=${port#:}
答え3
別のアイデア:
host=${1%:*}
port=${1##*:}
[ "$port" = "$1" ] && port=''
答え4
この文字列は、ここでは1行のドキュメントの構文ショートカットにすぎません。
$ set myhost:1234
$ IFS=: read A B <<EOF
> $1
> EOF
$ echo "$A"
myhost
$ echo "B"
1234