Извлечь информацию между двойными кавычками из .csv

Извлечь информацию между двойными кавычками из .csv

У меня возникли проблемы со скриптом, обрабатывающим файл .csv.

Информация о .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

Вот как следует разделять информацию: MsgID,Дата,Кому,Копия,СК,Тема,Текст,Статус,Временная метка

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

Проблемы с основной частью возникают по двум причинам: «,» в тексте разрывается, когда я пытаюсь запустить скрипт, а другая причина — разрывы строк в тексте.

Вот сценарий, который я делал:

#!/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

решение1

Оболочка — это простоочень плохой инструмент для анализа текста. Его следует использовать только для самых простых задач, и, возможно, даже не тогда. Он медленный, неэффективный, его очень сложный синтаксис делает его подверженным ошибкам, и в нем отсутствуют самые основные инструменты обработки текста. Вдобавок ко всему, CSV — это сложный формат, который допускает вложенные и многострочные записи. Попытка разобрать CSV-файл в оболочке просто напрашивается на неприятности.

Поэтому вместо этого используйте правильный язык программирования с поддержкой парсинга CSV. Например, в 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))

Я сохранил скрипт выше как foo.pyи затем:

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

Как вы видите, он правильно распознал все поля. Так что, чтобы также отправить почту, вы можете сделать что-то вроде этого (адаптировано отсюда):

#!/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)

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Судя по имеющимся у вас опциям, вы, похоже, используете BSD mail. У меня нет доступа к рабочей системе с установленным этим инструментом, поэтому я не смог протестировать скрипт отправки почты выше. Хотя это должно послужить по крайней мере хорошим началом.

решение2

Вы можете использовать такой инструмент, как Миллер (https://github.com/johnkerl/miller), специализирующийся на работе со структурированными текстовыми данными.

В примере, начиная с этого input.txtфайла

#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

и бег

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

у тебя будет

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

Если вы хотите удалить возврат каретки в поле body, вы можете выполнить команду

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

иметь

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

Связанный контент