¿Cómo expandir este selector de columna 2 de awk con el parámetro Bash $1?

¿Cómo expandir este selector de columna 2 de awk con el parámetro Bash $1?

Estoy intentando hacer que mi script bash sea una función con el parámetro de entrada Bash, pero la sintaxis de AWK está causando un problema. Código AWK original

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

Pseudocódigo con 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

El problema es la pieza print $"${colN}".

La salida actual no logra capturar la segunda columna y toma toda la línea, etc.

-0.21,-0.245
-0.205,-0.22

Tener solo print $colNno es correcto, ya que siempre toma la primera columna independientemente del valor en $1.

Ejemplo del caso de uso donde lo llamo por bash code.bash 2; o guión completoaquíque funciona si no codifica qué columna elegir (1/2) en todos los archivos CSV de dos columnas para el resultado unido de las segundas columnas

#!/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

Entradas multicolumna 1.csv 2.csv 3.csv

-0.21,-0.245
-0.205,-0.22

Salida deseada

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

SO: Debian 8.5
Bash 4.30

Respuesta1

La entrada de su ejemplo tiene los mismos valores en el primer y segundo campo para todos los archivos (y los mismos valores para todos los archivos), lo que realmente no ayuda a comprender el caso de uso exacto. Después de todo, si realmente desea el mismo valor tres veces y puede obtenerlo de cualquier campo de cualquier archivo de entrada, ni siquiera necesita verificar los otros dos archivos. Puedes usar simplemente:

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

Por supuesto, esto no funciona con entradas reales, solo con entradas de ejemplo. (Esfuércese por mejorar su entrada/salida de ejemplo para este tipo de pregunta; le ayudará alote.)


Si hacemos las suposiciones de que:

  • Siempre tienes exactamente tres archivos de entrada
  • Llamado input1.csv, input2.csv,input3.csv
  • Con exactamente dos columnas cada una.
  • Y quieres la segunda columna de cada archivo.

Puede hacer esto más fácilmente con una combinación de Awk y paste(y la globalización de archivos de shell):

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

Si esas suposiciones son erróneas, culpe a los ejemplos deficientes de entrada/salida. ;)

Respuesta2

Para responder a su pregunta como se indica, dado

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

y un script de prueba simple

$ cat col.bash
#!/bin/bash

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

puede verificar que $colefectivamente hace referencia a la columna deseada, es decir

$ ./col.bash 2
b
e
h
k

Si eso no funciona en su caso, entonces hay otros factores en juego. De todos modos, existen formas mucho más sencillas de extraer columnas de varios archivos.

Respuesta3

Usar Bash y AWK en este caso será muy difícil. No pude resolver el problema con las soluciones propuestas aquí. Vas a tener muchos problemas con "/ '/... así que aquí es necesaria una sola herramienta.

Úselo tal gawkcomo se discute en el hilo.Herramienta de selección de 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, lea la respuesta completa de200_success aquícon excelentes explicaciones.

información relacionada