スペースを追加せずにbashで文字列パラメータを複数行に分割する方法

スペースを追加せずにbashで文字列パラメータを複数行に分割する方法

次のコマンドを実行しています。

some_command --flag "foo\
    bar\
    quux" arg2

これにより文字列がに渡されますfoo\tbar\tquux

タブを使用せずに(または他のスペース文字を追加せずに)このパラメータを渡す方法を探しています。しかし、インデントを保ちます(私のスクリプトを読むことができるように)。

答え1

some_command --flag "$(printf '%s' foo\
    bar\
    quux)" arg2

一番読みやすいわけではありませんが、そうします。 「foo」、「bar」、および「quux」をコマンドの引数とprintfフォーマット%s文字列として渡します。引数より少ない書式文字が指定されている場合、書式文字列は必要に応じて繰り返されます。これは%s%s%s、3つの文字列すべてをスペースなしで順番に印刷するのと同じです。最後に、「foobarquux」コマンドの出力は引数にprintf置き換えられますsome_command

答え2

ヘルパー機能を使用してください。

concat () (
    IFS=
    printf '%s' "$*"
)

printf '"%s"\n' "$(concat "foo" \
    "bar" \
    "baz" )"

これは出力されます

"foobarbaz"

または、最初に引数の文字列ビットを配列に入れてから、実際の引数を別々に作成します(配列付きのシェルを使用しているとします)。

concat () (
    IFS=
    printf '%s' "$*"
)

args=(
    "foo"
    "bar"
    "baz"
)

concat_args=$( concat "${args[@]}" )

printf '"%s"\n' "$concat_args"

上記のPOSIXシェルと同じ:

concat () (
    IFS=
    printf '%s' "$*"
)

set -- \
   "foo" \
   "bar" \
   "baz"

concat_args=$( concat "$@" )

printf '"%s"\n' "$concat_args"

実行の関数本体は、concat独自のサブシェルで実行されます(これがすぐに(...)実行されるアクションです)。これは、変更が関数IFSに対してローカルであることを意味します。

関数で"$*"置換を使用する理由は純粋に審美的です。"$@"プログラムが"$*"拡大される予定です。一つ印刷する文字列ですprintf。この場合、実際の接続は$*区切り文字(空白)なしでシェル拡張によって行われます$IFS。代わりに、それを使用すると、フォーマット文字列が繰り返し適用される"$@"複数の個別の文字列に展開されます。printfこの場合、接続は次のようになります。副作用特定の書式文字列をprintf

または同じアイデア(実際の引数文字列を別々に生成)ですが、対応するヘルパー関数がない場合

arg=\
"foo"\
"bar"\
"baz"

printf '"%s"\n' "$arg"

printf '"%s"\n'すべての場合において、上記はあなたのものですsome_command --flag

関連情報