この Bash 変数を機能させるにはどうすればよいですか: myformat="--format=fuller --date=format:%Y-%m-%d T%H"

この Bash 変数を機能させるにはどうすればよいですか: myformat="--format=fuller --date=format:%Y-%m-%d T%H"

これは、Bash が単語のグループ化と変数の展開をどのように処理するかについての質問です。非常に具体的な例を使ってこの質問を説明します。

bash$ git log --format=fuller --date=format:"%Y-%m-%d T%H"    # This works.

# Sample output:
commit aba22155684
Author:     SerMetAla
AuthorDate: 2018-04-12 T23
Commit:     SerMetAla
CommitDate: 2018-04-12 T23

    Here is the commit message.

これが機能することを望みます:

bash$ git log "$myformat"    # It should print the same stuff.

1 つの Bash 変数だけでこれを実現する方法がわかりません。2 つの変数を使用した動作例を次に示します。

# Define the two variables:
bash$ mypref="--format=fuller"
bash$ mydate="--date=format:%Y-%m-%d T%H"    # Note: No " after the colon.

# Now use it:
bash$ git log "$mypref" "$mydate"    # It works.

問題はこれです: どうすればこれを 1 つの Bash 変数だけで動作させることができるでしょうか? 可能ですか?

主な問題:

git log --format=fuller --date=format:"%Y-%m-%d T%H"
                       |                       ^ This space is inside one argument.
                       |
                       ^ This space separates two arguments.

通常の文字列変数を使いたいです。配列変数は使いたくないし、 も使いたくないし$'...'、関数も使いたくないし、エイリアスも使いたくないです。文字列が不変で、コマンドの先頭にない場合は、Bash 変数にすべきな気がします。

関数を使えば、かなり読みやすい方法で簡単に解決できます。他の Bash トリックを使えば、恐ろしい方法で解決できます。文字列変数を使いたいです。

答え1

配列変数を使いたくない

あなたはその仕事に適したツールを拒否しています。では、次のものを試してみてくださいeval:

$> foo='a "b c"'
$> printf "%s\n" $foo
a
"b
c"
$> eval printf '"%s\n"' $foo
a
b c
$>

あなたの場合は次のようになります:

myformat='--format=fuller --date=format:"%Y-%m-%d T%H"'
eval git log $myformat

答え2

これはよくある質問です。https://mywiki.wooledge.org/BashFAQ/050

簡単に言えば、これを解決するには、引数を配列に入れることです。

myformat=("$mypref" "$mydate")
git log "${myformat[@]}"

非常に大まかな回避策として、printf引用符付きの書式指定子を使用することもできます。

printf -v myformat '%q %q' "$mypref" "$mydate"
git log $myformat

関連情報