引用符付き印刷形式でエンコードされた行のリンク

引用符付き印刷形式でエンコードされた行のリンク

私は、「ソフトニューライン」シーケンス(等号、キャリッジリターン、ニューライン)で終わる75の文字列で構成される多くの引用された印刷可能な添付ファイルを含む巨大なmboxファイル(8.8GB)を持っています。

特定の正規表現のすべてのアイテムのmboxコンテンツを検索したいと思います。ただし、特定の一致は複数行に分割できるため、正規表現検索を実行する前に各ソフトニューラインシーケンスを削除する必要があります。

これを行うための最良の方法を見つけるのが難しいです。私が見つけたGNU sedソリューションここsedにファイル全体を1行として処理するように指示するため、失敗します。行の長さが長いため、INT_MAXsedはエラーメッセージで終了します。私も見ましたが、解決方法がありました。ここリップグレップを使用してください。しかし、これは実際に行をリンクしません。等号は削除されますが、等号のある行はまだ次の行から分離されています。

答え1

最後に説明するのは、mboxを電子メールコンテンツに解析してから(添付ファイルの数を数えている)、そのコンテンツを表示することです。正しいこと!

こうしてください。実際にmboxファイルをメッセージに解析すると、少し気分が良くなります。ここに私の頭の上があります。テストされていませんが、エディタコードでは赤ではありません。

#!/usr/bin/env python3
import mailbox
import re as regex

pattern = regex.compile("BRIANSREGEX")

mb = mailbox.mbox("Briansmails.mbox", create=False)
for msg in mb:
    print(f"{msg['Subject']}")
    for part in msg.walk():
        print(f"| {part.get_content_type()}, {part.get_content_charset()}")
        print("-"*120)
        payload = part.get_payload(decode=True)
        charset = part.get_content_charset
        if type(payload) is bytes:
            content = ""
            try:
                content = payload.decode(charset)
            except:
                # print("failed to decode")
                try:
                    content = payload.decode() # try ascii
            match = pattern.search(content)
            # do what you want with that match…
            if match:
                print(f"| matched at {match.start()}")
        print("-"*120)

答え2

私はMarcus Müllerの答えに親指を立てましたが、これは彼の答えに基づいたバージョンです。

#!/usr/bin/env python3
import mailbox
import re
import sys

byte_pattern = re.compile(b"https?://[^/]*imgur.com/[a-zA-Z0-9/.]*")
str_pattern = re.compile("https?://[^/]*imgur.com/[a-zA-Z0-9/.]*")

mb = mailbox.mbox(sys.argv[1], create=False)
for msg in mb:
    for part in msg.walk():
        if part.is_multipart():
            continue
        payload = part.get_payload(decode=True)
        if type(payload) is bytes:
            # first, search it as a binary string
            for match in byte_pattern.findall(payload):
                print(match.decode('ascii'))
            # then, try to decode it in case it's utf-16 or something weird
            charset = part.get_content_charset()
            if charset and charset != 'utf-8':
                try:
                    content = payload.decode(charset)
                    for match in str_pattern.findall(content):
                        print(match)
                except:
                    pass
        else:
            print('failed to get message part as bytes')

リーフではなくノードを含む深さ優先ナビゲーションを実行するため、partツリーのリーフノードではなくマルチパートメッセージになる可能性があります。walk

リーフノードの場合のみ、最初にパターンをバイト文字列として取得し、指定された文字セット(UTF-8以外の場合)を使用してテキストにデコードしようとします。 (最も多く使用されているUTF-8の場合、すでにバイト列で検索されています。)

関連情報