citar apenas se a variável não estiver vazia

1

Eu tenho um antigo script bash que gostaria de melhorar. Este script usou muitas variáveis e, em alguns casos, algumas das variáveis são referenciadas, mas vazias ou não definidas. Isso geralmente não é um problema aqui porque o script foi projetado assim desde o início.

No entanto, comecei a usar o shellcheck que reclama muito sobre a falta de citações. Por isso, acrescentei citações e encontrei um inconveniente para o qual não tenho uma boa solução.

Existem muitas linhas que se parecem com isso:

cmd $param1 $param2 $param3 $param4

Se um dos parâmetros estiver vazio ou não configurado, ainda está funcionando e o número de parâmetros que o cmd recebe é reduzido. Mas se eu começar a adicionar citações

cmd "$param1" "$param2" "$param3" "$param4"

O cmd sempre obterá 4 parâmetros, independentemente de algum deles estar vazio.

Por que isso é perfeitamente claro? A solução alternativa também é clara (verificando o vazio antes de usar o parâmetro), mas é feia e requer muito código adicional.

Então, estou procurando uma solução inteligente que a) omite um param (incluindo as aspas!) se estiver vazio b) adiciona o texto apenas para variáveis não vazias

    
por uli42 10.08.2017 / 13:27

2 respostas

2

Qual shell você está usando para este script? Eu suponho que seja / bin / sh

A única entidade semelhante a um array que você tem em um shell POSIX são os parâmetros posicionais. Você poderia fazer isso:

set --  # clear the positional parameters
for param in "$param1" "$param2" "$param3" "$param4"; do
    if [ -n "$param" ]; then
        # append this param to the positional params
        set -- "$@" "$param"
    fi
done
# invoke the command with the positional params, properly quoted
cmd "$@"

Se você quiser ser mais inteligente, envolva a invocação de cmd em uma função:

invoke_cmd() {
  n="$#"  # remember the original number of params
  # append to the args list only if non-empty                    
  for arg; do [ -n "$arg" ] && set -- "$@" "$arg"; done
  # discard the original params (including the empty ones)
  shift "$n"
  # and invoke the cmd
  cmd "$@"
}
invoke_cmd "$param1" "$param2" "$param3" "$param4"

Para o bash real, simplifique

invoke_cmd() {
  local args=()
  for arg; do [[ "$arg" ]] && args+=("$arg"); done
  cmd "${args[@]}"
}
invoke_cmd "$param1" "$param2" "$param3" "$param4"
    
por 10.08.2017 / 17:13
1

Outra opção (além do que o @glennjackman descreveu) é usar a expansão condicional com :+ para incluir uma variável (adequadamente citada) somente se estiver definida e não vazia:

cmd ${param1:+"$param1"} ${param2:+"$param2"} ${param3:+"$param3"} ${param4:+"$param4"}

(Observação: a expansão condicional está na especificação posix , na seção 2.6.2; mas não tenho certeza se todos os shells posix respeitarão adequadamente as aspas duplas no valor alternativo.)

Se você estiver disposto a fazer alterações mais extensas no script e restringi-lo ao bash (ou seja, se estiver usando um #!/bin/bash ou #!/usr/bin/env bash shebang), é geralmente mais limpo acumular parâmetros em um array:

cmd_parameters=() # start with an empty array
if [ something ]; then
    cmd_parameters+=("$param1") # Add an element -- note that the () are critical here!
fi
if [ something_else ]; then
    cmd_parameters+=("$param2")
fi
...etc
cmd "${cmd_parameters[@]}"

Tenha em atenção que é perfeitamente possível misturar estas abordagens, incluindo a utilização do truque :+ para adicionar condicionalmente um elemento de matriz:

cmd_parameters+=(${param3:+"$param3"})

e / ou mistura de matriz e parâmetros condicionais para o mesmo comando:

cmd "${cmd_parameters[@]}" ${param4:+"$param4"}

Além disso, tocando na sugestão de @ glennjackman de uma função de wrapper, seria possível escrever uma função de wrapper genérica:

conditional_args() {
    # invoke a command ($1) with any empty arguments omitted
    args=()
    for arg; do
        args+=(${arg:+"$arg"})
    done
    "${args[@]}" # Note that the first "arg" is actually the command itself
}

conditional_args cmd "$param1" "$param2" "$param3" "$param4"
    
por 10.08.2017 / 22:37

Tags