行末のバックスラッシュがあまりにも多くのスペースを占めるのはなぜですか?

行末のバックスラッシュがあまりにも多くのスペースを占めるのはなぜですか?

私は考えた:

#!/bin/bash
cmd --options \
    option=value,\
    option=value,\
    option=value,\
    option=value

しかし、それを実行した後、次のようなbash -x結果が得られます。

cmd --options option=value, option=value, option=value, option=value

これによりエラーが発生します。

Bashが自動的にこのスペースを入れないようにするにはどうすればよいですか?

答え1

まあ、各行の先頭にはスペースがあります。単一空間に圧縮されていても、 bash は自動的に削除しません。

これを完全に回避するには、次のようにスクリプトを作成します。

#!/bin/bash
command --options \
opt1=val1,\
opt2=val2,\
opt3=val3

答え2

文字列をコマンドに単一の引数として渡す必要がありますopt1=val1,opt2=val2,...が、編集のためにスクリプトの複数行にわたって分散したい場合は、配列を中間ステップとして使用し、コマンドを実行するときにすべての配列要素を連結できます。コマンド。

例えば

opts=(
    opt1=val1    # no commas here 
    opt2=val2    # but comments also work
    etc.
)
(IFS=,
 echo somecmd --options "${opts[*]}"   # echo for demonstration
)

その後、印刷somecmd --options opt1=val1,opt2=val2,etc.

(最初の角括弧ペアは配列割り当て構文の一部であり、2番目のペアはスクリプトの残りの部分が変更されないようにするためにサブシェルを起動します。特に、スクリプトが後で何もしないかリセットするIFS場合シェルは必要ないかもしれませんIFS

明らかに、これには配列をサポートする機能が豊富なシェルが必要です。 Bashに加えて、zshも使用できます。 kshでは、文字列(または少なくとも等号)を引用しなければ構造体と同じものに変わりません。複合変数


POSIX sh互換のソリューションが必要な場合、配列に最も近いのは位置引数のリストですが、そのうちの1つだけがあり、通常のコマンドとsetある程度動作するので、次のことを覚えておく必要があります。バックスラッシュバー(そしてコメントは使用できません)。

代わりに、次のように動作する必要があります。

args=$( <<EOF sed -e 's/^[[:space:]]*//' | tr '\n' ,
    opt1=val1
    opt2=val2
    etc.
EOF
)
args=${args%,}
echo somecmd --options "$args"  # echo for demonstration

答え3

別のオプション:

#!/bin/bash
cmd --options "$(printf "%s" \
    "option=value," \
    "option=value," \
    "option=value," \
    "option=value"
)"

printf "%s"空白なしで引数を印刷するので、結果は次のようになります。

cmd --options option=value,option=value,option=value,option=value

一部のコマンドは、単一の引数として渡される限り、スペースを完全に削除することもできます。したがって、簡単な引用(単語の分離を防ぐため)で十分です。たとえば、次のようにffmpegなります。

ffmpeg -i somefile.mp4 -vf "
    hflip,
    vflip,
    hue=s=0
" result.mp4

ただし、使用するコマンドは、これらのオプションの処理方法によって異なります。

動作しない場合に備えて、潜在的に複数回使用できるオプションもありますが--options(コマンドで許可する場合)、ffmpeg時には大丈夫です。

答え4

各オプションを1行に配置するには、異なるアプローチを試してみてください。

options="opt1=val1,"
options+="opt2=val2,"
options+="opt3=val3"
your_command --options "${options}"
# note: "command" being a bash builtin, I replaced it by "your_command"
# (command foo : bypasses any alias/function "foo" and instead launches "foo" from $PATH)

関連情報