/ bin / shのコロンで文字列を分割


9

私のdashスクリプトはの形式でパラメータを受け取りますhostname:port。つまり、

myhost:1234

一方、ポートはオプションです。

myhost

ホストとポートを別々の変数に読み込む必要があります。最初のケースでは、私は行うことができます:

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

しかし、ポートが省略されている場合、それは2番目のケースでは機能しません。echo ${1##*:}空の文字列ではなく、単にホスト名を返します。

バッシュでは、私はできる:

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

しかし、それはでは機能しませんdash

私は、上の文字列を分割することができ:、外部プログラムを(起動せずに、ダッシュではawktrなど)?


4
IPv6をサポートする場合は最後のコロンで分割し、角括弧内のコロンで分割しないでください
Ferrybig

@Ferrybig %%は(とは対照的に%)貪欲にします。したがって、少なくとも部分的には実際にこれを行います。で動作しません##
jpaugh、

回答:


18

ただやる:

case $1 in
  (*:*) host=${1%:*} port=${1##*:};;
  (*)   host=$1      port=$default_port;;
esac

あなたは変更することができますcase $1には、case ${1##*[]]}の値を考慮して$1のよう[::1](せずにIPv6アドレスポート部分)。

分割するには、split + glob演算子を使用できます(パラメーターの展開を引用符で囲まないでください)。

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ここ)でもオプション(ここ)でもないローカルスコープのサポートnoglobashおよびのような派生物dashは(および、4.4 ksh以降のAT&T実装と共に)実行するものの一部です)。zshbash

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

  • あなた-rはバックスラッシュがいくつかの特別な処理を受けることを意味することを忘れました。
  • それが分かれう[::1]:443[:1]:443の代わりに[、あなたが必要があると思いれる空の文字列(IFS=: read -r A B rest_ignoredまたは[::1]443(あなたがそのアプローチを使用できないため)
  • 改行文字が最初に出現した後はすべて削除されるため、任意の文字列では使用できません(またはで使用-d ''し、データにNUL文字が含まれていない場合を除きます)。ただし、ヒア文字列(またはヒアドキュメント)は、余分な改行文字!)zshbash
  • in zsh(構文がどこから来るか)とbash、ここでは、文字列は一時ファイルを使用して実装されるため、一般的には、${x#y}またはsplit + glob演算子を使用するよりも効率的ではありません。

7
2018年には、新年の抱負として、IPv6で壊れるスクリプトの作成をすべて停止する必要があります。
フィリポス

@Philipposは2週間遅れる!
RonJohn 2018年

@RonJohn:どういうわけか、20年では遅すぎます。
フィリポス

6

:別のステートメントでを削除するだけです。また、入力から$ hostを削除してポートを取得します。

host=${1%:*}
port=${1#"$host"}
port=${port#:}


1

here文字列は、1行のhereドキュメントの構文上のショートカットにすぎません。

$ set myhost:1234
$ IFS=: read A B <<EOF
> $1
> EOF
$ echo "$A"
myhost
$ echo "B"
1234
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.