Posso fazer uma introspecção do tipo de uma variável bash?

2

Estou escrevendo uma função que gera datas. Gostaria de permitir que o usuário personalize a saída fornecendo argumentos para date com uma variável de ambiente. Para preservar espaços em branco em strings de formato, gostaria de aceitar args em um array como este:

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

O usuário pode querer usar uma matriz se eles tiverem espaços em uma string de formato de data:

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

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

Mas, nesse caso, um array pode ser um exagero:

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

Eu não quero exigir uma matriz para casos simples como este. É possível dizer que tipo é a variável?

    
por Travis Wellman 13.04.2017 / 05:18

2 respostas

0

Parece-me que você pode querer deixar sua função passar qualquer opção de linha de comando diretamente para o GNU date , ao mesmo tempo tratando a não-opção numérica especialmente:

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 função bash passaria pelos seus argumentos de linha de comando e os salvaria no array opts , até atingir um argumento que é -- (a maneira padrão de sinalizar o fim das opções) ou que comece com um dígito. Cada argumento salvo em opts é desviado da lista de argumentos da linha de comando.

Uma vez encontrado um argumento que não é uma opção para date , assumimos que o restante dos argumentos são timestamps de épocas do UNIX e faça um loop sobre esses, chamando date com nossas opções salvas para cada timestamp. Veja o comentário no código para saber como fazer esse loop de forma mais eficiente.

Exemplo de invocações:

$ 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
    
por 25.11.2018 / 12:38
0

Você pode fazer isso muito mais facilmente desistindo de usar arrays e permitindo que o usuário especifique DATE_ARGS simplesmente como uma string que deve ser inserida na linha 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
    
por 25.11.2018 / 15:33