[英]Perl regular expression help (parse out column)
我被困在这里。 不知道为什么我的reg ex无法使用。 我有一个由管道分隔的带有一系列列的文本文件。 我需要提取第三列。
A|B|C|D|E|F|G|H|I
2011-03-03 00:00:00.0|1|60510271|254735|27751|BBB|1|-0.1619023623|-0.009865904
2011-03-03 00:00:00.0|1|60510270|254735|27751|B|3|-0.0064786612|-0.0063739185
2011-03-03 00:00:00.0|1|60510269|254735|27751|B|3|-0.0084998226|-0.009244384
$> head foo | perl -pi -e 's/^(.*)\|(.*)\|(.*)\|(.*)$/$3/g'
-0.1619023623
-0.0064786612
-0.0084998226
显然,输出的列不正确。
有什么想法吗?
通常,更容易/更简单(KISS)不要将正则表达式用于具有结构化分隔符的文件格式。 只需在“ |”上分割字符串 定界符并获得第三个字段。
awk -F"|" '{print $3}' file
使用Ruby(1.9+)
ruby -F"\|" -ane 'puts $F[2]' file
使用Perl,其类似于上面的Ruby单一代码。
perl -F"\|" -ane 'print $F[2]."\n"' file
.*
默认情况下,比赛将尽可能多的,因为它可以,所以你的RE被挑选出最后三列(和之前的一切),而不是前三个(一切后)。 您可以(至少)通过两种方式避免这种情况:(1)代替.*
,寻找[^|]*
,或(2)使您的重复运算符不贪心: .*?
代替.*
。
(或者,您可以显式地拆分字符串,而不是将整个内容与单个RE进行匹配。您可能想尝试两种方法,如果有关系的话,看看哪种方法效果更好。拆分可能会给出更长但更清晰的代码。)
如何使用真正的解析器而不是一起破解正则表达式? Text::CSV
应该可以完成这项工作。
my $csv = Text::CSV->new({sep_char => "|"});
您需要使模式变得贪婪-因此:
's/^(.*?)\\|(.*?)\\|(.*?)\\|(.*)$/$3/g'
首先想到的是Text :: CSV(由Matt B提到),但是如果数据看起来像示例,我会说split是正确的选择。
未经测试:
$> head foo | perl -le 'while (<>) { print (split m{|})[2]; }'
如果您真的想使用正则表达式,则可以使用以下命令:
s{^ [^\|]* \| [^\|]* \| ([^\|]*) \| .*$}{$1}gx;
(?<=\|)\d{8}
也许这会起作用(?<=\\|)
积极寻找|
字符后跟8位数字
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.