Bashで配列拡張にマルチ文字区切り文字を使用する方法は?

Bashで配列拡張にマルチ文字区切り文字を使用する方法は?

私は問題を最も簡単なケースに縮小しました。myscript.sh次の内容を含むスクリプトがあるとします。

#!/bin/bash
IFS='%20'
echo "$*"

次のようにコマンドを実行すると、出力は次のようになります。

me@myhost ~ $ ./myscript.sh fee fi fo fum
fee%fi%fo%fum

これは、bashマニュアルページに記載されているとおりに予想される動作です。

   *      Expands  to  the positional parameters, starting from one.  When
          the expansion occurs within double quotes, it expands to a  sin-
          gle word with the value of each parameter separated by the first
          character of the IFS special variable.  That is, "$*" is equiva-
          lent to "$1c$2c...", where c is the first character of the value
          of the IFS variable.  If IFS is unset, the parameters are  sepa-
          rated  by  spaces.   If  IFS  is null, the parameters are joined
          without intervening separators. 

しかし、私が得たいのは出力です。

fee%20fi%20fo%20fum

したがって、単一文字の代わりに複数の文字区切り文字フィールドを使用してください。

これを行う方法はありますかbash


修正する:

以下のmikeservのデータと以下の記事に基づいています。なぜprintfがechoより優れているのですか?、私は次のようになりました(上記の例に示すように、再び最も単純なケースに単純化されました)。

#!/bin/bash
word="$1"
shift
if [ "$#" -gt 0 ] ; then
    word="$word$(printf '%%20%s' "$@")"
fi
printf '%s\n' "$word"
unset word

答え1

printf出力の後に続く各引数に対応する書式文字列を適用します。これはbash、引数リストに区切り文字列を適用するために使用できるシェル組み込み関数です。

たとえば、

printf %s:delimit: arg1 arg2 arg3

arg1:delimit:arg2:delimit:arg3:delimit:

問題は、printfいいえ止める引数の末尾に書式文字列を適用するので、最後の引数には区切り文字が追加されます。場合によっては、次のようにすることができます。

printf %b:delimit: \\0150 \\0145 \\0171\\c

h:delimit:e:delimit:y

printf%bCおよび8進数エスケープは、いくつかの形式があり、特定の点で出力を出力する形式を持つytes%bとして解釈されます\c。したがって、printf上記のyの後には:delimit:文字列はありません。対応する書式文字列は、そうでなければ表示で終わるためです。

したがって、各パラメータを文字通り解釈したい場合そして末尾の区切り文字がない場合は、パラメータリスト自体を処理する必要があります。

set -- arg1 arg2 arg3
for arg do shift
    set -- "$@" :delimit: "$arg"
done; shift
printf %s "$@"

arg1:delimit:arg2:delimit:arg3

答え2

あなたはzsh使用することができますj:string: パラメータ拡張フラグ:

set -- fee fi fo fum
delims=%20
print -rl ${(j:$delims:)@}

答え3

使用中のbash場合、または変数拡張が有効になっている他のシェルを使用していて、引数の中にスペースがない場合は、次のようにします。

#!/bin/bash
line=$*
echo "${line// /:delimiter:}"

IFS空白の場合は、before before変数を設定して別のフィールド区切り文字を使用する必要がありますline

関連情報