Extraer información entre comillas dobles en .csv

Extraer información entre comillas dobles en .csv

Tengo algunos problemas con un script que analiza un archivo .csv

Información sobre .csv:

#1,13/8/2020,[email protected],[email protected],,Subject,"Dear Dude,

Information have been updated. Please login to APP to review by 30th August 2020. Thank you.

Best regards,
Mr. Mack",Pending,13/8/2020 12:35

Así es como se debe dividir la información: ID de mensaje, fecha, para, CC, CCO, asunto, cuerpo, estado, marca de tiempo

MsgID=#1
Date=13/8/2020
[email protected]
[email protected]
BCC=
Subject=Subject
Body=Dear Dude,
Information have been updated. Please login to APP to review by 30th August 2020. Thank you.
Best regards,
Mr. Mack
Status=Pending
Timestamp=13/8/2020 12:35

Los problemas que tengo son con la parte del cuerpo por dos razones, el "," en el texto que se rompe cuando intento ejecutar el script y la otra razón son los saltos de línea en el texto.

Este es el guión que estaba haciendo:

#!/bin/bash

export TIMESTAMP="$( date '+%d/%m/%Y %H:%M:%S' )"
INPUT=/tmp/test.csv
OUTPUT=/tmp/test.csv.out
OLDIFS=$IFS
IFS=','
[ ! -f $INPUT ] && { echo "$INPUT file not found"; exit 99; }
while read msgid dat to cc bcc subject body status timesta
do
        echo "MSG ID : $msgid" 
        echo "Date : $dat"
        echo "To : $to"
        echo "CC : $cc"
        echo "BCC : $bcc"
        echo "Subject : $subject"
        echo "Body : $body"
        echo "Status : $status"
        echo "Timestamp : $timesta"
echo $body | mail -s "$subject" $to -c $cc -b $bcc
printf "$msgid,$dat,$to,$cc,$bcc,$subject,$body,Sent,$TIMESTAMP" >> $OUTPUT
done < $INPUT
IFS=$OLDIFS

Respuesta1

El caparazón es sólo unMuy mala herramienta para analizar texto.. Sólo deberías usarlo para las tareas más simples, y probablemente ni siquiera entonces. Es lento, ineficiente, su sintaxis muy complicada lo hace propenso a errores y carece de las herramientas de procesamiento de texto más básicas. Además de esto, CSV es un formato complejo que permite entradas anidadas y de varias líneas. Intentar analizar un archivo CSV en el shell solo es buscar problemas.

Por lo tanto, utilice un lenguaje de programación adecuado que admita el análisis CSV. Por ejemplo, en Python:

#!/bin/python3
import csv
import sys

with open(sys.argv[1], newline='') as csvfile:
    fieldnames = ("MsgID","Date","To","CC","BCC",
                  "Subject","Body","Status","Timestamp")
    reader = csv.reader(csvfile, delimiter=',',
    for row in reader:
        for fieldName, value in zip(fieldnames,row):
            print("%s: %s" % (fieldName,value))

Guardé el script anterior como foo.pyy luego:

MsgID: #1
Date: 13/8/2020
To: [email protected]
CC: [email protected]
BCC: 
Subject: Subject
Body: Dear Dude,

Information have been updated. Please login to APP to review by 30th August 2020. Thank you.

Best regards,
Mr. Mack
Status: Pending
Timestamp: 13/8/2020 12:35

Como puedes ver, ha reconocido correctamente todos los campos. Entonces, para enviar también el correo, puedes hacer algo como esto (adaptado de aquí):

#!/bin/python3
import csv
import sys
import subprocess
import os

def send_message(to, cc, bcc, subject, body):
    try:
        process = subprocess.Popen(['mail', '-s', subject, '-c', cc, '-b', bcc, to],
                                   stdin=subprocess.PIPE)
    except Exception as error:
      print(error)
    process.communicate(body)


with open(sys.argv[1], newline='') as csvfile:
    reader = csv.reader(csvfile, delimiter=',')
    for row in reader:
        (msgID, date, to, cc, bcc, subj, body, status, timestamp) = row
        send_message(to, cc, bcc, subj, body)

DESCARGO DE RESPONSABILIDAD: Parece que estás usando BSD mailsegún las opciones que tienes. No tengo acceso a un sistema que funcione con esa herramienta instalada, por lo que no pude probar el script de envío de correo anterior. Al menos debería servir como un buen comienzo.

Respuesta2

Podrías usar una herramienta como Miller (https://github.com/johnkerl/miller), especializado en trabajar con datos de texto estructurado.

En un ejemplo a partir de este input.txtarchivo

#1,13/8/2020,[email protected],[email protected],,Subject,"Dear Dude,

Information have been updated. Please login to APP to review by 30th August 2020. Thank you.

Best regards,
Mr. Mack",Pending,13/8/2020 12:35

y corriendo

mlr --implicit-csv-header --c2x cat then label MsgID,Date,To,CC,BCC,Subject,Body,Status,Timestamp input.txt

usted tendrá

MsgID     #1
Date      13/8/2020
To        [email protected]
CC        [email protected]
BCC
Subject   Subject
Body      Dear Dude,

Information have been updated. Please login to APP to review by 30th August 2020. Thank you.

Best regards,
Mr. Mack
Status    Pending
Timestamp 13/8/2020 12:35

Si desea eliminar el retorno de carro en el campo del cuerpo, puede ejecutar

mlr --implicit-csv-header --c2x cat then label MsgID,Date,To,CC,BCC,Subject,Body,Status,Timestamp then put '$Body=gsub($Body,"\n"," ")' input.txt

tener

MsgID     #1
Date      13/8/2020
To        [email protected]
CC        [email protected]
BCC
Subject   Subject
Body      Dear Dude,  Information have been updated. Please login to APP to review by 30th August 2020. Thank you.  Best regards, Mr. Mack
Status    Pending
Timestamp 13/8/2020 12:35

información relacionada