是否有一种方法可以使用bash来获取. email的特定文本内容?



对于bash和。eml文件都是新手,所以请告诉我…

我有一个文件夹,里面有许多保存的。eml文件,我想要一个bash脚本(如果bash不可能做到这一点,我愿意使用python,或者zsh,或者perl——以前从未使用过perl,但学习它可能会很好),它将在包含特定文本短语的行之后和下一个空行之前打印电子邮件内容。

我还希望这个脚本能够组合以"="结尾的连续行。(不以"="结尾的行)符号应该在新的行上继续打印。

我用手动创建的。txt文件进行的所有测试都工作得很好,但是当我使用实际的。eml文件时,事情就停止工作了。

下面是示例.eml文件的一部分:

(.eml file continues above)
Content-Type: text/plain; charset="Windows-1252"
Content-Transfer-Encoding: quoted-printable
testing
StartLine (This is where stuff begins)
This is a line that should be printed.
This is a long line that should be printed. Soooooooooooooooooooooooooooooo=
Loooooooooooooooooooooooonnnnnnnnnggggg. Soooooooooooooooooooooooooooooo L=
oooooooooooooooooooooooonnnnnnnnnggggg. Soooooooooooooooooooooooooooooo Loo=
oooooooooooooooooooooonnnnnnnnnggggg.
This is where things should stop (no more printing)
Don=92t print me please!
Don=92t print me please!
Don=92t print me please!


[This message is from an external sender.]
(.eml file continues below)

我希望脚本输出:

This is a line that should be printed.
This is a long line that should be printed. Soooooooooooooooooooooooooooooo Loooooooooooooooooooooooonnnnnnnnnggggg. Soooooooooooooooooooooooooooooo Loooooooooooooooooooooooonnnnnnnnnggggg. Soooooooooooooooooooooooooooooo Loooooooooooooooooooooooonnnnnnnnnggggg.
下面是我的脚本:
#!/bin/bash
files="/Users/username/Desktop/emails/*"
specifictext="StartLine"
for f in $files
do
begin=false
previous=""
while read -r line
do
if [[ -z "$line" ]] #this doesn't seem to be working right
then
begin=false
fi
if [[ "$begin" = true ]]
then
if [[ "${line:0-1}" = "=" ]] #this also doesn't appear to be working
then
previous=$previous"${line::${#line}-1}"
else
echo $previous$line
fi
fi
if [[ $line = "$specifictext"* ]]
then
begin=true
fi
done < "$f"
done

这将成功跳过包含$specifictext的行之前的所有内容,但随后它将打印出每个电子邮件的整个剩余部分,而不是在下一个空行停止。这样的:

$ ./printeml.sh 
This is a line that should be printed.
This is a long line that should be printed. Soooooooooooooooooooooooooooooo=
Loooooooooooooooooooooooonnnnnnnnnggggg. Soooooooooooooooooooooooooooooo L=
oooooooooooooooooooooooonnnnnnnnnggggg. Soooooooooooooooooooooooooooooo Loo=
oooooooooooooooooooooonnnnnnnnnggggg.
This is where things should stop (no more printing)
Don=92t print me please!
Don=92t print me please!
Don=92t print me please!


[This message is from an external sender.]
(continues printing remainder of .eml)

正如您在上面看到的,我遇到的另一个问题是,我想获得带有"="的合并行。最后会有迹象,但这不起作用。除了使用实际的.eml文件外,我对测试文件所做的所有测试似乎都工作得很好。我认为这是一个隐藏字符在。eml文件的问题,但我不确定这是如何工作的。

我在MacOS 12.4上使用bash版本3.2.57(1)

这两个问题都源于。eml文件使用Windows行结束符(实际上是MIME行结束符;该规范是为通过TELNET协议传输而设计的,因此规定使用CRLF而不是裸LF)。Bash不理解这些,它将回车符视为一个普通字符,它恰好是每行的最后一个字符。因此,空行实际上是包含回车符的单字符行,以=结尾的行实际上以=结尾,后跟回车符($'=r')。当您检查最后一个字符时,您将获得回车符,当然,它永远不会是=

但这只是问题的一部分。您可以将该文件转换为UNIX行结束符(尽管此时它不是一个有效的.eml文件),或者考虑代码中的cr。然而,连续行后面的等号只是printable"的一部分。Content-Encoding头告诉您消息体正在使用的编码模式。您可能遇到的另一件事是Q-P消息不能合法地包含ASCII范围之外的任何字符,但必须使用=xx和两个十六进制数字来表示这些字符。任何代码点为>127将被=xx替换为十六进制的代码-任何文字等号也将被替换为=3D

因此,理想情况下,您应该使用一些能够理解MIME消息的库,而不是尝试使用自己的代码来进行解码。也许使用MIME::Parser模块的Perl脚本是合适的?或者你也可以用Python给出的答案来回答这个问题。

最新更新