¿Cómo puedo hacer que funcione esta variable Bash? myformat="--format=fuller --date=format:%Y-%m-%d T%H"

¿Cómo puedo hacer que funcione esta variable Bash? myformat="--format=fuller --date=format:%Y-%m-%d T%H"

Esta es una pregunta sobre cómo Bash maneja la agrupación de palabras y la expansión de variables. Demostraré la pregunta con un ejemplo muy 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.

Me gustaría que esto funcione:

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

No sé cómo hacerlo realidad con una sola variable Bash. Aquí hay un ejemplo funcional con DOS variables:

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

El problema es este: ¿Cómo puedo hacer que esto funcione con una sola variable Bash? ¿Es posible?

El problema principal:

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

Me gustaría utilizar una variable de cadena normal. No quiero usar una variable de matriz, no quiero usar $'...', no quiero usar una función, no quiero usar un alias. Cuando la cadena es inmutable y cuando no está al principio del comando, parece que debería ser una variable Bash.

Podría resolver esto muy fácilmente con una función de una manera bastante legible. Podría resolverlo con otros trucos de Bash de una manera que sería horrible. Quiero usar una variable de cadena.

Respuesta1

No quiero usar una variable de matriz

Está rechazando una herramienta adecuada para el trabajo. Bueno, puedes probar con eval:

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

En tu caso sería como:

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

Respuesta2

Esta es una pregunta frecuente común.https://mywiki.wooledge.org/BashFAQ/050

Brevemente, la forma de resolverlo es poner los argumentos en una matriz.

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

Como solución muy sencilla, también puedes utilizar printfel especificador de formato de cotización:

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

información relacionada