Saída de cada coluna N da entrada

5

Estou tentando escrever um script para imprimir todas as N colunas de um arquivo, fornecendo a coluna inicial, o valor incremental e o nome do arquivo como parâmetros de tempo de execução. Abaixo está meu script:

file=$1
st=$2
inc=$3

echo $file
echo $st
echo $inc

awk '{for (i = $st; i <= NF; i += $inc) printf ("%s%c", $i, i + $inc <= NF ? " " : "\n");}' $file

Não consigo obter o resultado. Alguém pode ajudar-me? Minhas entradas podem ser como script.sh file_name 1 4

Agradecemos antecipadamente.: -)

    
por Radhakrishnan Rk 28.09.2017 / 13:59

2 respostas

9

Variáveis do shell não se tornam automaticamente awk de variáveis (também em awk , variáveis são expressas como var , não $var , que é o campo var th ). Se você quiser passar a variável shell para awk , uma abordagem simples é usar o ambiente:

#! /bin/sh -
file=$1
ST=$2
INC=$3

export ST INC
awk '
  {
    sep = ""
    for (i = ENVIRON["ST"]; i <= NF; i += ENVIRON["INC"]) {
      printf "%c%s", sep, $i
      sep = OFS
    }
    printf "\n"
  }' < "$file"

Lembre-se de citar suas variáveis de shell e que awk não pode obter nomes de arquivos arbitrários como argumento (pois trata alguns com = ou um chamado - especialmente).

Uma alternativa para passar variáveis para awk é usar -v awkvar="$shellvar" ou awkvar="$shellvar" argumentos após o script awk, mas eles não podem ser usados para strings arbitrárias, pois sequências de escape são expandidas nelas ( \ se torna \ e \n se torna uma nova linha por exemplo).

awk -v st="$st" -v inc="$inc" '{for (i = st; i <= NF; i += inc)...}' < "$file"

ou

awk  '{for (i = st; i <= NF; i += inc)...}' st="$st" inc="$inc" < "$file"

seria OK aqui, já que essas variáveis servem apenas para conter números (portanto, nenhuma barra invertida).

Não importa o que você faça,

awk 'for (i = '"$st"'; i <= NF; i += '"$inc"')...'

e muito menos

awk 'for (i = '$st'; i <= NF; i += '$inc')...'

que tem o shell expande os valores das variáveis $st e $inc no código passado para awk , pois isso cria vulnerabilidades de injeção de comando (por exemplo, para valores de st like system("reboot") ) .

    
por 28.09.2017 / 14:06
3

Eu corrigi seu script para que agora funcione. Houve dois erros. (a) você tem que passar variáveis de shell para awk manualmente (isso é feito usando -v awk_var="$shell_var" syntax) e (b) você não deve usar $ para denotar uma variável, $ é usado apenas para posição de campo. / p>

file=$1
st=$2
inc=$3

echo $file
echo $st
echo $inc

awk -v st="$st" -v inc="$inc" '{for (i = st; i <= NF; i += inc) printf ("%s%c", $i, i + inc <= NF ? " " : "\n");}' $file
    
por 28.09.2017 / 14:14