私は質問を(私が信じる)最も単純なケースに減らしています。スクリプトがあるとしましょう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
printf
は、出力時にそれに続く各引数にフォーマット文字列を適用します。これはbash
シェルに組み込まれており、引数のリストに区切り文字列を適用するために使用できます。
例えば:
printf %s:delimit: arg1 arg2 arg3
arg1:delimit:arg2:delimit:arg3:delimit:
重要なのは、printf
は引数の最後にフォーマット文字列を適用しないstopであるため、最後の1つには区切り文字が追加されます。これは、場合によっては処理できます。
printf %b:delimit: \\0150 \\0145 \\0171\\c
h:delimit:e:delimit:y
printf
は、Cと8進数のエスケープを特定の種類の形式の%b
ytesとして解釈し、%b
形式では、特定の時点で出力を\c
utします。これが理由です。 printf
は、フォーマット文字列が示すように、上記のyの後に:delimit:
文字列を続けません。
したがって、すべての引数を文字通りに解釈する必要がある場合および末尾の区切り文字を使用しない場合は、引数リスト自体の中で問題に対処する必要があります。
set -- arg1 arg2 arg3
for arg do shift
set -- "$@" :delimit: "$arg"
done; shift
printf %s "$@"
arg1:delimit:arg2:delimit:arg3
zsh
では、j:string:
パラメータ拡張フラグ を使用できます。
set -- fee fi fo fum
delims=%20
print -rl ${(j:$delims:)@}