Contando con un fichero del siguiente contenido:
1111,2222,3333,4444
aaaa,bbbb,cccc,dddd
Busco obtener un archivo igual al original pero al que le falta una enésima columna como, para n = 2 (o puede ser 3)
1111,2222,4444
aaaa,bbbb,dddd
o, para n = 0 (o puede ser 1)
2222,3333,4444
bbbb,cccc,dddd
Un archivo real puede tener gigabytes de longitud y decenas de miles de columnas.
Como siempre en estos casos, sospecho que los magos de la línea de comandos pueden ofrecer una solución elegante... :-)
En mi caso real, necesito eliminar 2 primeras columnas, lo que se puede hacer eliminando una primera columna dos veces en una secuencia, pero supongo que sería más interesante generalizar un poco.
Respuesta1
Creo que esto es específico para eliminar de GNU coreutils:
$ cut --complement -f 3 -d, inputfile
1111,2222,4444
aaaa,bbbb,dddd
Normalmente especificas los campos que deseas mediante -f, pero al agregar --complement inviertes el significado, naturalmente. De 'hombre cortado':
--complement
complement the set of selected bytes, characters or fields
Una advertencia: si alguna de las columnas contiene una coma, se cortará, porque cut no es un analizador CSV de la misma manera que lo es una hoja de cálculo. Muchos analizadores tienen ideas diferentes sobre cómo manejar las comas de escape en CSV. Para el caso simple de CSV, en la línea de comando, cortar sigue siendo el camino a seguir.
Respuesta2
Si los datos están formados simplemente por columnas separadas por comas:
cut -d , -f 1-2,4-
También puedes usar awk, pero es un poco incómodo porque, si bien borrar un campo es fácil, eliminar el separador requiere algo de trabajo. Si no tienes ningún campo vacío, no está tan mal:
awk -F , 'BEGIN {OFS=FS} {$3=""; sub(",,", ","); print}'
Si tiene un CSV real, donde pueden aparecer comas dentro de los campos si se citan correctamente, necesita unbiblioteca CSV real.
Respuesta3
Usando una herramienta compatible con CSV para eliminar las dos primeras columnas de un archivo de entrada CSV sin encabezado:
$ cat file
1111,2222,3333,4444
aaaa,bbbb,cccc,dddd
$ mlr --csv -N cut -x -f 1,2 file
3333,4444
cccc,dddd
La -x
opción a la cut
operación enMolinero( mlr
) hace que la operaciónexcluirlos campos nombrados (en este caso, los campos número 1 y 2). Si los datos CSV hubieran tenido encabezados, habríamos podido usar campos con nombre -f
(la -N
opción también debería eliminarse en este escenario).
Dado que Miller admite CSV, puede manejar campos entre comillas correctamente que contienen comas, comillas y nuevas líneas incrustadas.
Respuesta4
Pruebe el siguiente comando para eliminar columnas usando el índice.
dropColumnCSV --index=0 --file=file.csv
Esto funcionaría si las columnas están separadas por comas, comosedLos comandos se utilizan dentro de la función para eliminar cadenas.
dropColumnCSV() {
# argument check
while [ $# -gt 0 ]; do
case "$1" in
--index=*)
index="${1#*=}"
;;
--file=*)
file="${1#*=}"
;;
*)
printf "* Error: Invalid argument. *\n"
return
esac
shift
done
# file check
if [ ! -f $file ]; then
printf "* Error: $file not found.*\n"
return
fi
# sed remove command index zero
if [[ $index == 0 ]]; then
sed -i 's/\([^,]*\),\(.*\)/\2/' $file
# sed remove command index greater than zero
elif [[ $index > 0 ]]; then
pos_str=$(for i in {1..$(seq "$index")}; do echo -n '[^,]*',; done| sed 's/,$//') ;
sed -i 's/^\('$pos_str'\),[^,]*/\1/' $file
fi
}