Como posso fazer esta variável Bash funcionar: myformat="--format=fuller --date=format:%Y-%m-%d T%H"

Como posso fazer esta variável Bash funcionar: myformat="--format=fuller --date=format:%Y-%m-%d T%H"

Esta é uma questão sobre como o Bash lida com o agrupamento de palavras e a expansão de variáveis. Vou demonstrar a questão com um exemplo bem específico:

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.

Eu gostaria que isso funcionasse:

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

Não sei como fazer isso acontecer com apenas uma variável Bash. Aqui está um exemplo prático com DUAS variáveis:

# 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.

O problema é o seguinte: como posso fazer isso funcionar com apenas uma variável Bash? É possível?

O problema principal:

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

Eu gostaria de usar uma variável de string normal. Não quero usar uma variável de array, não quero usar $'...', não quero usar uma função, não quero usar um alias. Quando a string é imutável e não está no início do comando, parece que deveria ser uma variável Bash.

Eu poderia facilmente resolver isso com uma função de uma maneira bastante legível. Eu poderia resolver isso com outros truques do Bash de uma forma que seria horrível. Eu quero usar uma variável de string.

Responder1

Eu não quero usar uma variável de array

Você está rejeitando uma ferramenta adequada para o trabalho. Bem, você pode tentar com eval:

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

No seu caso seria assim:

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

Responder2

Este é um FAQ comum.https://mywiki.wooledge.org/BashFAQ/050

Resumidamente, a maneira de resolver isso é colocar os argumentos em um array.

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

Como uma solução alternativa muito simples, você também pode usar printfo especificador de formato de cotação:

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

informação relacionada