我想只从文件中提取数字并组织为CSV。
自:
Aa:40, Bint:02 : Bstring = 0x13 Ccc Num = 52 Dfloat = 164.0
Aa:40, Bint:03 : Bstring = 0x1B Ccc Num = 10 Dfloat = 10.6
Aa:41, Bint:04 : Bstring = 0x1A Ccc Num = 10 Dfloat = 1.6
为:
40,02,0x13,52,164.0
40,03,0x1B,10,10.6
41,04,0x1A,10,1.6
我可以用Python re.findall
(如下所示)
for line in sys.stdin:
print (",".join(re.findall(r'\d+.?\w+', line)))
实现相同的perl方法是什么?
答案 0 :(得分:4)
您正在从字符串中提取数值。
你可以这样做:
m/(\d+)/g;
当然,既然您还包括.
和x
:
m/(\d[\d\.xA-F]+)/ig;
或作为一个班轮:
perl -nle 'print join ",", m/(\d[\d\.xA-F]+)/ig;'
n
是&#34;将其换成while ( <> ) {
。
这意味着您可以管道STDIN
或在其后指定文件 - 例如perl -nle 'print join ",", m/(\d[\d\.xA-F]+)/gi;' somefile
cat somefile | perl -nle 'print join ",", m/(\d[\d\.xA-F]+)/gi;'
l
是自动选择。它chomps
换行并在打印后重新添加
e
执行此代码段。
这有效地使上述一个班轮:
BEGIN { $/ = "\n"; $\ = "\n"; }
LINE: while (defined($_ = <ARGV>)) {
chomp $_;
print join(',', /(\d[\d\.xA-F]+)/gi);
}
这给出了;
40,02,0x13,52,164.0
40,03,0x1,10,10.6
41,04,0x1,10,1.6
看起来像您想要的输出。
答案 1 :(得分:3)
foo.pl
- python代码段的直接翻译
print join (',', m/(\d+.?\w+)/g), "\n" foreach <STDIN>;
需要注意的重要一点是在寻找匹配时使用/g
。这个标志将有效地说我们对字符串中存在的每个匹配感兴趣,而不仅仅是第一个。
当然, one-liner (你特别要求的)可以写成如下,对于未经训练的眼睛来说可能更具可读性:
foreach my $line (<STDIN>) {
my @data = $line =~ m/(\d+.?\w+)/g);
print join (',', @data), "\n";
}
% cat data.txt
Aa:40, Bint:02 : Bstring = 0x13 Ccc Num = 52 Dfloat = 164.0
Aa:40, Bint:03 : Bstring = 0x1B Ccc Num = 10 Dfloat = 10.6
Aa:41, Bint:04 : Bstring = 0x1A Ccc Num = 10 Dfloat = 1.6
% cat data.txt| perl foo.pl
40,02,0x13,52,164.0
40,03,0x1B,10,10.6
41,04,0x1A,10,1.6
答案 2 :(得分:1)
尝试这样的事情:
# Declare the regex
my $is_num = qr {
(?: 0x[0-9a-fA-F]+ ) # Match stuff like 0x1B
| # Or
\d+ (?: \.\d+ )? # 5 or 5.2
}x;
chomp(my @data = <DATA>);
for(@data){
my @new;
push @new, $1 while /($is_num)/g;
$_ = join ",", @new;
}
print "$_\n" for @data;
__DATA__
Aa:40, Bint:02 : Bstring = 0x13 Ccc Num = 52 Dfloat = 164.0
Aa:40, Bint:03 : Bstring = 0x1B Ccc Num = 10 Dfloat = 10.6
Aa:41, Bint:04 : Bstring = 0x1A Ccc Num = 10 Dfloat = 1.6
40,02,0x13,52,164.0
40,03,0x1,10,10.6
41,04,0x1,10,1.6
我确信有更好的方法可以做到这一点。这是我想到的第一个
答案 3 :(得分:0)
# Declare the regex
my $is_num = qr {
(?: 0x[0-9a-fA-F]+ ) # Match stuff like 0x1B
| # Or
\d+ (?: \.\d+ )? # 5 or 5.2
}x;
chomp(my @data = <DATA>);
for(@data){
s/.*? ($is_num)/$1,/xg;
s/\W+$//x;
}
print "$_\n" for @data;
40,02,0x13,52,164.0
40,03,0x1B,10,10.6
41,04,0x1A,10,1.6