我正在尝试编写一个perl正则表达式来匹配包含11列的第5列文件。还有一个不是数据的序言和页脚。关于如何做到这一点的任何好的想法?这是我到目前为止所做的:
if($line =~ m/\A.*\s(\b\w{9}\b)\s+(\b[\d,.]+\b)\s+(\b[\d,.sh]+\b)\s+.*/i) {
这就是表格的样子:
No. Form 13F File Number Name ____ 28-________________ None [Repeat as necessary.] FORM 13F INFORMATION TABLE TITLE OF VALUE SHRS OR SH /PUT/ INVESTMENT OTHER VOTING AUTHORITY NAME OF INSURER CLASS CUSSIP (X$1000) PRN AMT PRNCALL DISCRETION MANAGERS SOLE SHARED NONE Abbott Laboratories com 2824100 4,570 97,705 SH sole 97,705 0 0 Allstate Corp com 20002101 12,882 448,398 SH sole 448,398 0 0 American Express Co com 25816109 11,669 293,909 SH sole 293,909 0 0 Apollo Group Inc com 37604105 8,286 195,106 SH sole 195,106 0 0 Bank of America com 60505104 174 12,100 SH sole 12,100 0 0 Baxter Internat'l Inc com 71813109 2,122 52,210 SH sole 52,210 0 0 Becton Dickinson & Co com 75887109 8,216 121,506 SH sole 121,506 0 0 Citigroup Inc com 172967101 13,514 3,594,141 SH sole 3,594,141 0 0 Coca-Cola Co. com 191216100 318 6,345 SH sole 6,345 0 0 Colgate Palmolive Co com 194162103 523 6,644 SH sole 6,644 0 0
答案 0 :(得分:1)
我认为正则表达式对此有点过分。
我要做的是清理输入并在文件上使用Text::CSV_XS,指定记录分隔符(sep_char)。
答案 1 :(得分:1)
像以太一样,另一种工具适合这项工作。
@fields = split /\t/, $line;
if (@fields == 11) { # less than 11 fields is probably header/footer
$the_5th_column = $fields[4];
...
}
答案 2 :(得分:1)
如果你这么长时间写一个正则表达式,你至少应该使用x
标志来忽略空格,重要的是允许空格和注释:
m/
whatever
something else # actually trying to do this
blah # for fringe case X
/xi
如果你发现很难阅读自己的正则表达式,其他人会发现它是不可能的。
答案 3 :(得分:0)
我的第一个想法是,示例中的示例数据非常严重。很高兴看到它嵌入在一些<pre>...</pre>
标签中,因此将保留列。
如果你正在处理柱状数据,你可以使用substr()或unpack()比使用正则表达式更容易。您可以使用正则表达式来解析数据,但是我们大多数人一直在编写Perl编程时也了解到正则表达式并不是第一个抓取很多次的工具。这就是你得到其他评论的原因。正则表达式是一种强大的武器,但它也很容易用脚射击自己。
http://perldoc.perl.org/functions/substr.html
http://perldoc.perl.org/functions/unpack.html
更新
在美国证券交易委员会埃德加网站上发现一点点后,我发现13F文件的格式很好。而且,你应该没有问题找出如何使用substr和/或解包来处理它们。
FORM 13F INFORMATION TABLE VALUE SHARES/ SH/ PUT/ INVSTMT OTHER VOTING AUTHORITY NAME OF ISSUER TITLE OF CLASS CUSIP (x$1000) PRN AMT PRN CALL DSCRETN MANAGERS SOLE SHARED NONE - ------------------------------ ---------------- --------- -------- -------- --- ---- ------- ------------ -------- -------- -------- 3M CO COM 88579Y101 478 6051 SH SOLE 6051 0 0 ABBOTT LABS COM 002824100 402 8596 SH SOLE 8596 0 0 AFLAC INC COM 001055102 291 6815 SH SOLE 6815 0 0 ALCATEL-LUCENT SPONSORED ADR 013904305 172 67524 SH SOLE 67524 0 0
如果您看到13F文件未格式化,如您的示例所示,那么您无法正确查看,因为某些文件中的列之间存在选项卡。
我查看了68个文件以了解其中的内容,然后编写了一个快速的基于解包的例程并得到了这个:
3M CO, COM, 88579Y101, 478, 6051, SH, , SOLE, , 6051, 0, 0 ABBOTT LABS, COM, 002824100, 402, 8596, SH, , SOLE, , 8596, 0, 0 AFLAC INC, COM, 001055102, 291, 6815, SH, , SOLE, , 6815, 0, 0 ALCATEL-LUCENT, SPONSORED ADR, 013904305, 172, 67524, SH, , SOLE, , 67524, 0, 0
基于其他一些文件,这里有一些关于如何处理它们的想法:
某些文件使用标签来分隔列。这些都很容易解析,你不需要正则表达式来拆分列。 0001031972-10-000004.txt似乎就是这样,看起来与你的例子非常相似。
有些文件使用标签来对齐列,不将它们分开。您需要弄清楚如何将多个选项卡运行压缩到单个选项卡中,然后可能会拆分选项卡以获取列。
其他人使用空白行垂直分隔行,因此您需要跳过空白行。
其他人允许换行到下一行(就像电子表格会在一个不够宽的列中。要弄清楚如何解决这个问题并不难,但如何做到这一点仍然留作练习你。
有些使用居中的列对齐,导致数据中的前导和尾随空格。 s/^\s+//;
和s/\s+$//;
将成为您的朋友。
我看到的最有趣的一个似乎是正确创建的,然后在第78列进行了单词包装,这让我想到一些白痴将他们的电子表格或报告加载到他们的文字处理器然后保存了它。读取这是摆脱包装回车的两步过程,然后重新处理数据以解析列。作为一项附加任务,他们在分页数据中也有列标题。
您应该能够获得100%的解析文件,但是由于使用了制表符和空行以及嵌入的列标题,您可能希望使用几种不同的解析方法。
啊,处理来自荒野的数据的乐趣。