
Ich habe Probleme mit einem Skript, das eine CSV-Datei analysiert
Informationen zur CSV-Datei:
#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
So sollten Informationen aufgeteilt werden: MsgID,Datum,An,CC,BCC,Betreff,Text,Status,Zeitstempel
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
Ich habe aus zwei Gründen Probleme mit dem Hauptteil: Das „,“ im Text, das umbricht, wenn ich versuche, das Skript auszuführen, und der andere Grund sind die Zeilenumbrüche im Text.
Dies ist das Skript, das ich erstellt habe:
#!/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
Antwort1
Die Schale ist nur einsehr schlechtes Tool zum Textparsing. Sie sollten es nur für die einfachsten Aufgaben verwenden und wahrscheinlich nicht einmal dann. Es ist langsam, ineffizient, seine sehr komplizierte Syntax macht es fehleranfällig und es fehlen die grundlegendsten Textverarbeitungstools. Darüber hinaus ist CSV ein komplexes Format, das verschachtelte und mehrzeilige Einträge zulässt. Der Versuch, eine CSV-Datei in der Shell zu analysieren, ist einfach nur ein Ärgernis.
Verwenden Sie stattdessen eine geeignete Programmiersprache mit Unterstützung für CSV-Parsing. In Python beispielsweise:
#!/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))
Ich habe das obige Skript wie folgt gespeichert foo.py
und dann:
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
Wie Sie sehen, wurden alle Felder korrekt erkannt. Um die E-Mail auch zu versenden, können Sie Folgendes tun (angepasst von hier):
#!/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)
HAFTUNGSAUSSCHLUSS: Den Optionen nach, die Sie haben, scheinen Sie BSD zu verwenden mail
. Ich habe keinen Zugriff auf ein funktionierendes System mit diesem installierten Tool, daher konnte ich das obige Skript zum Senden von E-Mails nicht testen. Es sollte jedoch zumindest als guter Anfang dienen.
Antwort2
Sie könnten ein Werkzeug wie Miller verwenden (https://github.com/johnkerl/miller), spezialisiert auf die Arbeit mit strukturierten Textdaten.
Im Beispiel ausgehend von dieser input.txt
Datei
#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
und läuft
mlr --implicit-csv-header --c2x cat then label MsgID,Date,To,CC,BCC,Subject,Body,Status,Timestamp input.txt
du wirst haben
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
Wenn Sie den Wagenrücklauf im Textfeld entfernen möchten, können Sie Folgendes ausführen:
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
haben
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