/bin/sh のコロンで区切られた文字列

/bin/sh のコロンで区切られた文字列

私のdashスクリプトは次の形式のパラメータを使用しますhostname:port

myhost:1234

ポートはオプションです。つまり、次のようになります。

myhost

ホストとポートを別々の変数として読み取る必要があります。最初のケースでは、次のようにすることができます。

HOST=${1%%:*}
PORT=${1##*:}

ただし、2番目のケースでは、ポートが省略された場合は機能せず、空の文字列ではecho ${1##*:}なくホスト名のみが返されます。

Bashでは、次のことができます。

IFS=: read A B <<< asdf:111

しかし、ここではdash

外部プログラム(など):を呼び出さずに文字列をダッシュ​​に分割できますか?awktr

ベストアンサー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に同意します。)$IFSnoglobthis)&T実装も含む))。ashdashkshzshbash

それ自体IFS=: read A B <<< "$1"にいくつかの問題があることに注意してください。

  • -rこれはバックスラッシュが特別な処理を経なければならないことを忘れています。
  • [::1]:443それはandの[代わりに:1]:443[の文字列に分割されます(これにはIFS=: read -r A B rest_ignoredor [::1]andが必要です443(これにはその方法は使用できません)。
  • 改行が最初に発生した後のすべての項目を削除するため、任意の文字列では機能しません(または内で使用せず、-d ''データzshbashNUL文字が含まれていない場合)。ただし、herestrings(またはheredocs)は追加の文字列を追加します。改行文字!)
  • zsh(文法ソース)と でbash文字列は一時ファイルを使用して実装されているため、通常${x#y}または分割+glob演算子を使用するよりも効率が悪くなります。

おすすめ記事