Execute a saída de outro comando, com substituição de variável

2

No bash, frequentemente executo programas awk com muitas variáveis predefinidas. Na maioria das vezes eu uso os mesmos nomes de variáveis no bash e no awk, então chamo o awk da seguinte forma:

awk -v var1="$var1" -v var2="$var2" -v var3="$var3" ....... '
    # awk code
' 

Isso fica um pouco tedioso quando eu tenho muitos nomes de variáveis para digitar. Idealmente, gostaria de poder executar algo como o seguinte:

$(awkline var1 var2 var3 ......) '
   # awk code
'

onde a saída do comando "awkline" é o formato correto do comando awk. Por exemplo, o programa "awkline" poderia se parecer com:

#!/bin/bash
line="awk"
for i in $*; do line="$line -v $i="'"$'"$i"'"'; done
echo $line

Se eu executar "awkline a b c", obtenho o que espero:

awk -v a="$a" -v b="$b" -v c="$c"

No entanto, se eu tentar executar o comando como $ (awkline abc), o valor da variável a inside awk se torna (literalmente incluindo as aspas) "$ a", e não o valor de a, como eu gostaria . Como substituo todas as ocorrências de, e. $ a com o valor da variável a, para que eu possa executar o comando awkline?

    
por Matthew 13.12.2013 / 16:13

1 resposta

2

Não faça do awkline um script separado: isso significa que você terá que exportar todas as variáveis que deseja passar para o awk. Você pode torná-lo uma função que você adiciona ao seu .bashrc. Dessa forma, ele é executado no processo shell atual e tem acesso às suas variáveis do shell.

O manuseio dos parâmetros será complicado: você pode:

  1. passa as variáveis como uma string delimitada por espaço e deixa existir um número variável de argumentos de arquivo:

    awkline "var1 var2 var3" "awk body" file ...
    
  2. ou ter a função sempre lida de stdin e permitir um número variável de nomes de variáveis:

    cat file1 file2 ... | awkline var1 var2 ... "awk body"
    

Para codificar o primeiro:

awkline () {
    local variables=$1
    local body=$2
    shift 2
    local files=("$@")

    set -- $variables   # no quotes here, now the positional params are the var names
    local awk_cmd=(awk)
    for var; do
        awk_cmd+=(-v "$var=${!var}")
    done

    "${awk_cmd[@]}" "$body" "${files[@]}"
}     

Dado o uso em seu comentário, isso pode ser simplificado:

awkline () {
    local awk_vars=()
    for var in $1; do                   #  no quotes here
        awk_vars+=(-v "$var=${!var}")
    done
    shift
    awk "${awk_vars[@]}" "$@"
}     
    
por 13.12.2013 / 17:23

Tags