提取 .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

這是資訊應該如何劃分的: 訊息 ID、日期、收件者、副本、密件副本、主題、正文、狀態、時間戳

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 是一種複雜的格式,允許巢狀和多行條目。嘗試在 shell 中解析 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)

mail免責聲明:根據您擁有的選項,您似乎正在使用 BSD 。我無法存取安裝了該工具的工作系統,因此我無法測試上面的郵件發送腳本。不過,它至少應該是一個好的開始。

答案2

您可以使用 Miller 等工具(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

如果你想刪除正文字段中的回車符,你可以運行

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

相關內容