使用sed/awk修复损坏的mbox文件

使用sed/awk修复损坏的mbox文件,awk,sed,multiline,mbox,Awk,Sed,Multiline,Mbox,我有一堆旧的、继承的mbox文件,我想把它们转换成maildir。 问题:MBOX不完全符合RFC。 在某些(但不是全部)邮件中,有几个邮箱缺少“^From”行之前的空行,这导致mb2md无法将这些邮件彼此分开 例如: ... Text of mail 1 ... bla.... To unsubscribe, visit https:... From fetchmail Fri Nov 8 18:35:54 CET 2002

我有一堆旧的、继承的mbox文件,我想把它们转换成maildir。 问题:MBOX不完全符合RFC。 在某些(但不是全部)邮件中,有几个邮箱缺少“^From”行之前的空行,这导致mb2md无法将这些邮件彼此分开

例如:

...
Text of mail 1
... bla....    
To unsubscribe, visit https:...                      
From fetchmail Fri Nov  8 18:35:54 CET 2002          ## ^missing empty line above
...
Text of mail 2
...
现在,我正在寻找一种简单的方法,在任何与“^From”匹配的行之前插入一个空行,但前提是前面没有空行。必须进行一种流编辑,因为邮箱可能非常大

我经常使用sed,但我不熟悉多行匹配。今天尝试了几件事(经过修改后的cut'npaste)但没有成功:(

最后一次尝试是
sed-E':a;N;$!ba;s/\N(..*)\N从/g'/tmp/testfile//code>

只匹配最后一次出现的图案

sed/awk专家-你有什么提示吗

只匹配最后一次出现的图案

是的。正则表达式是贪婪的。
*
匹配所有内容,然后在匹配所有内容后,匹配来自
的最后一个
\n。匹配除换行符以外的所有内容,以匹配一行

sed -z -E 's/(\n[^\n]+\n)(From )/\1\n\2/g'
如果不想将整个文件读取到内存中,则必须在内存中读取至少两行。下面我将前一行放入保留空间-在每一行读取时将当前行与前一行相加以检查条件。检查后,打印前一行

sed -n -E '
      # Hold first line.
      1{h;b}
      # Append the line to hold space and switch hold space with pattern space
      # so that we have previous\ncurrent lines in pattern space.
      H;x
      # If we have From prepended by anything in previous line, add a newline
      /.+\nFrom /s/\n/\n\n/
      # Remove current line
      s/\n[^\n]*$//
      # Print previous line. Maybe with extra newline.
      p
      # If its last line, also print the holded last line
      ${x;p}
'
和一条单行线:

sed -nE '1{h;b};H;x;/.+\nFrom /s/\n/\n\n/;s/\n[^\n]*$//p;${x;p}'

任何时候使用的
sed
结构不是s、g和p(带-n),都是使用了错误的工具。如果出于某种原因不能使用
formail
,那么只需使用
awk

$ awk '/^From/ && p{print ""} {p=NF; print}' file
...
Text of mail 1
... bla....
To unsubscribe, visit https:...

From fetchmail Fri Nov  8 18:35:54 CET 2002          ## ^missing empty line above
...
Text of mail 2
...

这将在任何UNIX设备上使用任何awk都能工作,它一次只读取一行,因此无论您的输入文件有多大,它都能工作。

看,它可能比您手工编写的任何脚本更可靠地为您完成这项工作。这将需要将整个文件读取到内存中,OP说文件
可能非常庞大:A,n,$BA/<代码>。召唤Cthulu。不那么可笑——我假设它在某种类型的保持/缓冲中连接了输入行,但是我不知道它是一次取2行,还是一次读取整个文件,或者我不知道是否。它只是POSIX或GNU之类的东西。据我所知,只是一堆神秘的符文,但我只使用sed大约40年了:-)。我认为你应该在这里有一个空间
/^From/
,因为在邮件中通常有以
From:
开头的行。是的,这种方法非常脆弱<代码>正式邮件
是一条路要走。