¿Puedo introspeccionar el tipo de variable bash?

¿Puedo introspeccionar el tipo de variable bash?

Estoy escribiendo una función que genera fechas. Me gustaría permitir que el usuario personalice la salida proporcionando argumentos datecon una variable de entorno. Para preservar los espacios en blanco en las cadenas de formato, me gustaría aceptar argumentos en una matriz como esta:

function argdates {
    while [ $# -gt 0 ] && date "${DATE_ARGS[@]}" -d @$1
    do shift
    done
}

Es posible que el usuario desee utilizar una matriz si tiene espacios en una cadena con formato de fecha:

DATE_ARGS=( -u "+%y/%U, %I%p %a" )
argdates 1476395008 1493172224

# output:
# 16/41, 09PM Thu
# 17/17, 02AM Wed

Pero en este caso, una matriz podría ser excesiva:

DATE_ARGS="-u -Iseconds"
argdates 1476395008 1493172224

# output:
# date: invalid option -- ' '
# Try 'date --help' for more information.

# output should be:
# 2016-10-13T21:43:28+00:00
# 2017-04-26T02:03:44+00:00

No quiero requerir una matriz para casos simples como este. ¿Es posible saber de qué tipo es la variable?

Respuesta1

Me parece que es posible que desee permitir que su función pase cualquier opción de línea de comando directamente a GNU datemientras trata especialmente las no opciones numéricas:

argdates () {
    local -a opts
    local timestamp

    while [ "$#" -gt 0 ] && [ "$1" != '--' ] && [[ "$1" != [0-9]* ]]; do
        opts+=( "$1" )
        shift
    done
    [ "$1" = '--' ] && shift

    for timestamp do
        date "${opts[@]}" -d "@$timestamp"
    done

    # or, with a single invocation of "date":
    # printf '@%s\n' "$@" | date "${opts[@]}" -f -
}

Esta bashfunción revisaría sus argumentos de línea de comando y los guardaría en la optsmatriz, hasta que encuentre un argumento que sea --(la forma estándar de señalar el final de las opciones) o que comience con un dígito. Cada argumento guardado en optsse elimina de la lista de argumentos de la línea de comando.

Una vez que se ha encontrado un argumento que no es una opción date, asumimos que el resto de los argumentos son marcas de tiempo de época UNIX y los repasamos, llamando datecon nuestras opciones guardadas para cada marca de tiempo. Consulte el comentario en el código sobre cómo realizar este bucle de manera más eficiente.

Invocaciones de ejemplo:

$ argdates 1476395008 1493172224
Thu Oct 13 23:43:28 CEST 2016
Wed Apr 26 04:03:44 CEST 2017
$ argdates -- 1476395008 1493172224
Thu Oct 13 23:43:28 CEST 2016
Wed Apr 26 04:03:44 CEST 2017
$ argdates +%D 1476395008 1493172224
10/13/16
04/26/17
$ argdates +%F 1476395008 1493172224
2016-10-13
2017-04-26
$ argdates -u 1476395008 1493172224
Thu Oct 13 21:43:28 UTC 2016
Wed Apr 26 02:03:44 UTC 2017
$ argdates -u -Iseconds 1476395008 1493172224
2016-10-13T21:43:28+00:00
2017-04-26T02:03:44+00:00

Respuesta2

Podría hacerlo mucho más fácilmente renunciando al uso de matrices y permitiendo que el usuario especifique DATE_ARGSsimplemente como una cadena que debe insertarse en la línea de comando de date:

$ argdates(){
    for d; do printf %s "$DATE_ARGS" | xargs date -d "@$d"; done
}
$ DATE_ARGS='-u "+%y/%U, %I%p %a"' argdates 1476395008 1493172224
16/41, 09PM Thu
17/17, 02AM Wed
$ DATE_ARGS='-u -Iseconds' argdates 1476395008 1493172224
2016-10-13T21:43:28+00:00
2017-04-26T02:03:44+00:00

información relacionada