Unir múltiples comandos sed en un script para procesar el archivo CSV


34

Tener un archivo CSV como este:

HEADER
"first, column"|"second "some random quotes" column"|"third ol' column"
FOOTER

y buscando resultados como:

HEADER
first, column|second "some random quotes" column|third ol' column

en otras palabras, eliminar "FOOTER", comillas al principio, al final y alrededor |.

Hasta ahora este código funciona:

sed '/FOOTER/d' csv > csv1 | #remove FOOTER
sed 's/^\"//' csv1 > csv2 | #remove quote at the beginning
sed 's/\"$//' csv2 > csv3 | #remove quote at the end
sed 's/\"|\"/|/g' csv3 > csv4 #remove quotes around pipe

Como puede ver, el problema es que crea 4 archivos adicionales.

Aquí hay otra solución, que tiene el objetivo de no crear archivos adicionales y hacer lo mismo en un solo script. No funciona muy bien.

#!/bin/ksh

sed '/begin/, /end/ { 
        /FOOTER/d
        s/^\"//
        s/\"$//
        s/\"|\"/|/g 
}' csv > csv4

1
Como tiene citas, puede tener nuevas líneas en los campos. tu sedno va a funcionar con eso, solo con csv simplificado. Use un lenguaje de programación con una biblioteca que pueda manejar archivos CSV reales (Python / Perl / Ruby).
Anthon

Respuestas:


44

En primer lugar, como lo mostró Michael, puedes combinar todo esto en un solo comando:

sed '/^FOOTER/d; s/^\"//; s/\"$//; s/\"|\"/|/g' csv > csv1

Creo que algunas sedimplementaciones no pueden hacer frente a eso y podrían necesitar:

  sed -e '/^FOOTER/d' -e 's/^\"//' -e 's/\"$//' -e 's/\"|\"/|/g' csv > csv1

Dicho esto, parece que sus campos están definidos por |y solo desea eliminar "todo el campo, dejando los que están dentro del campo. En ese caso, podrías hacer:

$ sed '/FOOTER/d; s/\(^\||\)"/\1/g; s/"\($\||\)/\1/g' csv 
HEADER
first, column|second "some random quotes" column|third ol' column

O con GNU sed:

sed -r '/FOOTER/d; s/(^|\|)"/\1/g; s/"($|\|)/\1/g' csv 

También puedes usar Perl:

$ perl -F"|" -lane 'next if /FOOTER/; s/^"|"$// for @F; print @F' csv 
HEADER
first, column|second some random quotes column|third ol' column

13

Esto también funcionaría:

sed 's / ^ "//; s /" | "/ | / g; s /" "$ /" /'

Ejemplo:

$ echo '"this"|" and "ths""|" and "|" this 2"|" also "this", "thi", "and th""' | 
sed 's/^"//; s/"|"/|/g; s/""$/"/'
this| and "ths"| and | this 2| also "this", "thi", "and th"

versión bonita

sed '
s/^"//
s/"|"/|/g
s/""$/"/
$d
'

1
Esto no trata con el pie de página.
terdon

3
Pero eso eliminará la última línea sin importar su contenido. Si no hay FOOTER, eliminará los datos deseados.
terdon
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.