私は問題を最も簡単なケースに縮小しました。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
%b
Cおよび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
。