Bash - função de registro - printf

Aug 30 2020

Estou tentando criar um logger para o bash. O problema é que a impressão direta está funcionando, mas o LOGGER_FUNC não controla a matriz corretamente.

Atualmente, posso imprimir os dados que devem ser registrados:

DEBUG_data_ARRAY=(hi ho no bugs here no)
printf "\n%s" "${DEBUG_data_ARRAY[@]}" printf "\n%s %s" "${DEBUG_data_ARRAY[@]}"

Onde o printf deve ser substituído por:

LOGGER_FUNC "\n%s" "${DEBUG_data_ARRAY[@]}" LOGGER_FUNC "\n%s %s" "${DEBUG_data_ARRAY[@]}"

Função logger:

LOGGER_FUNC () {
    format=$1 message=$2
    if [[ $VERBOSE == 0 ]]; then printf "${format[@]}" "${message[@]}" fi if [[ $VERBOSE == 1 ]]; then
         printf "${format[@]}" "${message[@]}" >> $DEBUG_FILE fi if [[ $VERBOSE == 2 ]]; then
        printf "${format[@]}" "${message[@]}"
        printf "${format[@]}" "${message[@]}" >> $DEBUG_FILE
    fi
}

O resultado esperado é o seguinte:

hi 
ho 
no 
bugs
here 
no

hi ho 
no bugs
here no

Respostas

4 JohnKugelman Aug 30 2020 at 20:35
format=$1 message=$2

Isso cria duas variáveis ​​escalares. Para fazer messageum array contendo $2, $3, $4, etc., escreve:

format=$1
message=("${@:2}")

Então, como formaté um escalar, você pode simplesmente escrever em $formatvez de ${format[@]}:

if [[ $VERBOSE == 0 ]]; then
    printf "$format" "${message[@]}"
fi
if [[ $VERBOSE == 1 ]]; then printf "$format" "${message[@]}" >> "$DEBUG_FILE"
fi
if [[ $VERBOSE == 2 ]]; then printf "$format" "${message[@]}" printf "$format" "${message[@]}" >> "$DEBUG_FILE"
fi
1 LéaGris Aug 30 2020 at 21:08

Usando argumentos conforme fornecidos para a função:

#!/usr/bin/env sh

LOGGER_FUNC() {
  # shellcheck disable=SC2059 # Variable format string
  printf "$@" | case $VERBOSE in
    1) cat ;;
    2) cat >>"$DEBUG_FILE" ;; 3) tee -a "$DEBUG_FILE" ;;
  esac
}

Ou implemente um registrador de fluxo que não precise de argumentos para o conteúdo, mas tire-o de stdin:

#!/usr/bin/env bash

# stream_logger
# Log stdin with options
# &1: Verbose level:
#     1: stdout only
#     2: debug file only
#     3: both stdout and debug file
# &2: Optional debug file path
stream_logger() {
  if [ $# -eq 0 ] || [ "$1" -eq 0 ]; then
    cat >/dev/null
  elif [ $# -eq 1 ] || [ "$1" -eq 1 ]; then
    cat
  elif [ $# -eq 2 ]; then if [ "$1" -eq 2 ]; then
      cat >>"$2" elif [ "$1" -eq 3 ]; then
      tee -a "$2" fi fi } DEBUG_data_ARRAY=(hi ho no bugs here no) echo 'hello' | stream_logger # print nothing # Output to stdout only printf '\n%s' "${DEBUG_data_ARRAY[@]}" | stream_logger 1
printf '\n%s %s' "${DEBUG_data_ARRAY[@]}" | stream_logger 1 # Output to file1.log only printf '\n%s' "${DEBUG_data_ARRAY[@]}" | stream_logger 2 file1.log
printf '\n%s %s' "${DEBUG_data_ARRAY[@]}" | stream_logger 2 file1.log # Output to file2.log and stdout printf '\n%s' "${DEBUG_data_ARRAY[@]}" | stream_logger 3 file2.log
printf '\n%s %s' "${DEBUG_data_ARRAY[@]}" | stream_logger 3 file2.log