Como expandir este seletor da coluna 2 do awk com o parâmetro Bash $1?

Como expandir este seletor da coluna 2 do awk com o parâmetro Bash $1?

Estou tentando transformar meu script bash em uma função com parâmetro de entrada Bash, mas a sintaxe do AWK está causando um problema. Código AWK original

http://stackoverflow.com/a/19602188/54964
awk -F "\"*,\"*" '{print $2}' textfile.csv

Pseudocódigo com parâmetro Bash$1

file=$(awk -v colN="$1" -F "\"*,\"*" '{print $"${colN}"}' "${input}") 
# http://stackoverflow.com/a/19602188/54964 
# http://stackoverflow.com/a/19075707/54964

O problema é a parte print $"${colN}".

A saída atual não consegue capturar a segunda coluna e ocupa a linha inteira, etc.

-0.21,-0.245
-0.205,-0.22

Ter somente print $colNnão é correto, pois leva então sempre a primeira coluna independente do valor em $1.

Exemplo do caso de uso em que chamo by bash code.bash 2; ou roteiro completoaquique funciona se você não codificar qual coluna escolher (1/2) em todos os arquivos CSV de duas colunas para o resultado unido das segundas colunas

#!/bin/bash
ids=(101 118 201)
dir="/home/masi/Documents/CSV/"
index=0
for id in "${ids[@]}";
do
        input=$(echo "${dir}P${id}C1.csv")
        # take second column of the file here
        file=$(awk -v colN="$1" -F "\"*,\"*" '{print $colN}' "${input}") # http://stackoverflow.com/a/19602188/54964 # http://stackoverflow.com/a/19075707/54964

        Ecgs[${index}]="${file}"
        index=$index+1
done

Insere multicoluna 1.csv 2.csv 3.csv

-0.21,-0.245
-0.205,-0.22

Saída desejada

101,118,201
-0.245,-0.245,-0.245
-0.22,-0.22,-0.22

SO: Debian 8.5
Bash 4.30

Responder1

Sua entrada de exemplo tem os mesmos valores no primeiro e no segundo campo para todos os arquivos (e os mesmos valores para todos os arquivos), o que realmente não ajuda a entender o caso de uso exato. Afinal, se você realmente deseja o mesmo valor três vezes e pode obtê-lo de qualquer campo de qualquer arquivo de entrada, nem precisa verificar os outros dois arquivos. Você pode apenas usar:

cut -d, -f2 input.csv | paste -d, - - -

É claro que isso não funciona para entradas reais, apenas para entradas de exemplo. (Trabalhe para melhorar seu exemplo de entrada/saída para esse tipo de pergunta, isso ajuda muitomuito.)


Se fizermos as suposições de que:

  • Você sempre tem exatamente três arquivos de entrada
  • Chamado input1.csv, input2.csv,input3.csv
  • Com exatamente duas colunas cada
  • E você quer a segunda coluna de cada arquivo

Você pode fazer isso mais facilmente com uma combinação de Awk e paste(e globbing de arquivo shell):

paste -d, input[123].csv | awk -F, -v OFS=, '{print $2, $4, $6}'

Se essas suposições estiverem erradas, culpe os maus exemplos de entrada/saída. ;)

Responder2

Para responder à sua pergunta conforme declarado, dado

$ cat file
a,b,c
d,e,f
g,h,i
j,k,l

e um script de teste simples

$ cat col.bash
#!/bin/bash

awk -F, -vcol="$1" '{print $col}' file

você pode verificar se $colrealmente faz referência à coluna desejada, ou seja

$ ./col.bash 2
b
e
h
k

Se isso não funcionar no seu caso, existem outros fatores em jogo. Independentemente disso, existem maneiras muito mais simples de extrair colunas de vários arquivos.

Responder3

Usar Bash e AWK neste caso será muito difícil. Não consegui resolver o problema com as soluções aqui propostas. Você terá muitos problemas com "/ '/... então uma única ferramenta é necessária aqui.

Use exatamente gawkcomo discutido no tópicoFerramenta de seleção ECG Bash.

# https://codereview.stackexchange.com/a/146370/122105
#!/usr/bin/gawk -f

# https://www.gnu.org/software/gawk/manual/html_node/Join-Function.html
@include "join.awk"

BEGIN {
    FS = "\"*,\"*";
    last_row = 0;
}

BEGINFILE {
    rows[0][ARGIND] = gensub(".*P([0-9]*)C.*", "\\1", "g", FILENAME);
}

{
    rows[FNR][ARGIND] = $col;
    if (FNR > last_row) { last_row = FNR; }
}

END {
    for (r = 0; r <= last_row; r++) {
        print join(rows[r], 1, ARGC - 1, ",");
    }
}

Por favor, leia a resposta completa de200_success aquicom excelentes explicações.

informação relacionada