
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 $colN
no 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 $col
efectivamente 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 gawk
como 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.