@MaxMackie askubuntu.com/questions/88142/… . No puedo encontrar un mod allí a esta hora, así que lo señalé pidiéndoles que migren si están dispuestos; ya tiene una respuesta aceptada, así que no estoy seguro de si lo harán
Michael Mrozek
@MichaelMrozek, hmmm, ¿qué pasa generalmente en estas situaciones? ¿Simplemente conservamos los duplicados?
Además de cómo cortar y reorganizar los campos (cubiertos en las otras respuestas), existe el problema de los extravagantes campos CSV.
Si sus datos entran en esta categoría "peculiar", un poco de filtrado previo y posterior puede encargarse de ello. Los filtros que se muestran a continuación requieren los personajes \x01, \x02, \x03, \x04que no aparecen en cualquier parte de sus datos.
Aquí están los filtros envueltos alrededor de un simple awkvolcado de campo.
Nota: el campo cinco tiene un diseño de "campo entre comillas" no válido / incompleto, pero es benigno al final de una fila (dependiendo del analizador CSV). Pero, por supuesto, causaría resultados problemáticos no acelerados si se cambiara de su posición actual de fin de fila .
Actualizar; user121196 ha señalado un error cuando una coma precede a una cita final. Aquí está la solución.
Los datos
cat <<'EOF'>file
field one,"fie,ld,two",field"three","field,\",four","field,five"15111 N. Hayden Rd., Ste 160,",""
EOF
field one
"fie,ld,two"
field"three""field,\",four""field,five
"15111 N. Hayden Rd., Ste 160,"""
Aquí está el pre filtro , expandido con comentarios.
El filtro posterior es solo una inversión de \x01. \x02` \x03`\x04
sed -r '
s/^/,/# add a leading comma delimiter
s/\\"/\x01/g # obfuscate escaped quotation-mark (\")
s/,"([^"]*)"/,\x02\1\x03/g # obfuscate quotation-marks
s/,"/,\x02/# when no trailing quote on last field :MC # obfuscate commas embedded in quotes
s/\x02([^\x03]*),([^\x03]*)/\x02\1\x04\2/g
tMC
s/^,// # remove spurious leading delimiter'
¿Cómo eliminarías la enésima columna basada en este filtro?
user121196
@ user121196 - Como se mencionó en su oración inicial, esta respuesta muestra una manera de hacer que los datos CSV sean más consistentes ... por ejemplo. reemplazando temporalmente una coma incrustada con comillas con un carácter de ficha neutral ... y luego volviéndola a una coma después del movimiento / corte / eliminación. Nuevamente, como se mencionó, el paso mover / cortar / eliminar se reemplaza por un simple volcado de campo awk .
Peter.O
1
falla para este caso: "15111 N. Hayden Rd., Ste 160,", ""
usuario121196
@ user121196: Gracias por señalarlo. He actualizado la respuesta con una solución.
Peter
15
Esto depende de si su archivo CSV usa comas solo para delimitadores, o si tiene una locura como:
campo uno, "campo dos", campo tres
Esto supone que está utilizando un archivo CSV simple:
Eliminar una columna
Puede deshacerse de una sola columna de muchas maneras; Usé la columna 2 como ejemplo. Probablemente sea la forma más fácil de usar cut, lo que le permite especificar un delimitador -dy qué campos desea imprimir -f; esto le dice que se divida en comas y en el campo de salida 1 y los campos 3 hasta el final:
$ cut -d,-f1,3-/path/to/your/file
Si realmente necesita usar sed, puede escribir una expresión regular que coincida con los primeros n-1campos, el ncampo th y el resto, y omitir la salida nth (aquí nes 2, por lo que el primer grupo coincide con el 1tiempo :) \{1\}:
$ sed 's/\(\([^,]\+,\)\{1\}\)[^,]\+,\(.*\)/\1\3/'/path/to/your/file
Hay varias formas de hacerlo awk, ninguna de ellas particularmente elegante. Puede usar un forbucle, pero lidiar con la coma final es un dolor; ignorando que sería algo como:
Sin embargo, esto es molesto para las columnas más adelante
Duplicar una columna
En sedesto es en esencia la misma expresión que antes, pero también se captura la columna de destino e incluir ese grupo varias veces en la sustitución:
$ sed 's/\(\([^,]\+,\)\{1\}\)\([^,]\+,\)\(.*\)/\1\3\3\4/'/path/to/your/file
En awkla forma de bucle for, sería algo como (nuevamente ignorando la coma final):
Como es CSV, también lo necesitarás BEGIN { FS=","; OFS=","; }.
1
Creo que incluso FS = OFS = "," funcionará.
5
Dado un archivo delimitado por espacios en el siguiente formato:
12345
Puede eliminar el campo 2 con awk así:
awk '{ sub($2,""); print}' file
que vuelve
1345
Reemplace la columna 2 con la columna n donde sea apropiado.
Para duplicar la columna 2,
awk '{ col = $2 " " $2; $2 = col; print }' file
que vuelve
122345
Para cambiar las columnas 2 y 3,
awk '{temp = $2; $2 = $3; $3 = temp; print}'
que vuelve
13245
awk es generalmente muy bueno para tratar el concepto de campos . Si está tratando con un archivo CSV, y no con un archivo delimitado por espacios, simplemente puede usar
awk -F,
para definir su campo como una coma, en lugar de un espacio (que es el valor predeterminado). Hay una serie de buenos recursos awk en línea, uno de los cuales enumero como fuente a continuación.
No sé mucho al respecto awk, pero parece que está separado por espacios, incluso si el separador de campo está ,(el separador de campo solo controla cómo maneja la entrada)
Michael Mrozek
@MichaelMrozek: sí, es la variable OFS awk que controla el separador de campo de salida.
enzotib
Sí, y como mencioné en mi respuesta, puede pasar la opción -F a awk para cambiar el delimitador (por ejemplo, -F,)
Respuestas:
Además de cómo cortar y reorganizar los campos (cubiertos en las otras respuestas), existe el problema de los extravagantes campos CSV.
Si sus datos entran en esta categoría "peculiar", un poco de filtrado previo y posterior puede encargarse de ello. Los filtros que se muestran a continuación requieren los personajes
\x01
,\x02
,\x03
,\x04
que no aparecen en cualquier parte de sus datos.Aquí están los filtros envueltos alrededor de un simple
awk
volcado de campo.Nota: el campo cinco tiene un diseño de "campo entre comillas" no válido / incompleto, pero es benigno al final de una fila (dependiendo del analizador CSV). Pero, por supuesto, causaría resultados problemáticos no acelerados si se cambiara de su posición actual de fin de fila .
Actualizar; user121196 ha señalado un error cuando una coma precede a una cita final. Aquí está la solución.
Los datos
El código
La salida:
Aquí está el pre filtro , expandido con comentarios.
El filtro posterior es solo una inversión de
\x01
.\x02
`\x03
`\x04
fuente
Esto depende de si su archivo CSV usa comas solo para delimitadores, o si tiene una locura como:
Esto supone que está utilizando un archivo CSV simple:
Eliminar una columna
Puede deshacerse de una sola columna de muchas maneras; Usé la columna 2 como ejemplo. Probablemente sea la forma más fácil de usar
cut
, lo que le permite especificar un delimitador-d
y qué campos desea imprimir-f
; esto le dice que se divida en comas y en el campo de salida 1 y los campos 3 hasta el final:Si realmente necesita usar
sed
, puede escribir una expresión regular que coincida con los primerosn-1
campos, eln
campo th y el resto, y omitir la salidan
th (aquín
es 2, por lo que el primer grupo coincide con el1
tiempo :)\{1\}
:Hay varias formas de hacerlo
awk
, ninguna de ellas particularmente elegante. Puede usar unfor
bucle, pero lidiar con la coma final es un dolor; ignorando que sería algo como:Me resulta más fácil generar el campo 1 y luego usarlo
substr
para sacar todo después del campo 2:Sin embargo, esto es molesto para las columnas más adelante
Duplicar una columna
En
sed
esto es en esencia la misma expresión que antes, pero también se captura la columna de destino e incluir ese grupo varias veces en la sustitución:En
awk
la forma de bucle for, sería algo como (nuevamente ignorando la coma final):El
substr
camino:(A tcdyl se le ocurrió un método mejor en su respuesta )
Moviendo una columna
Creo que la
sed
solución se deriva naturalmente de las demás, pero comienza a ser ridículamente larga.fuente
awk
es tu mejor apuestaawk
imprime los campos por número, así que ...Para eliminar una columna, no imprimirla:
Para cambiar el orden:
Redireccionar a un archivo de salida.
awk
puede formatear la salida también.Awk formato de salida
fuente
BEGIN { FS=","; OFS=","; }
.Dado un archivo delimitado por espacios en el siguiente formato:
Puede eliminar el campo 2 con awk así:
que vuelve
Reemplace la columna 2 con la columna n donde sea apropiado.
Para duplicar la columna 2,
que vuelve
Para cambiar las columnas 2 y 3,
que vuelve
awk es generalmente muy bueno para tratar el concepto de campos . Si está tratando con un archivo CSV, y no con un archivo delimitado por espacios, simplemente puede usar
para definir su campo como una coma, en lugar de un espacio (que es el valor predeterminado). Hay una serie de buenos recursos awk en línea, uno de los cuales enumero como fuente a continuación.
Fuente para # 3
fuente
awk
, pero parece que está separado por espacios, incluso si el separador de campo está,
(el separador de campo solo controla cómo maneja la entrada)Esto funcionará para eliminar
Entrada
Salida
fuente