Perl - 使用正则表达式拆分命令 - 拆分数字和字符串

时间:2014-11-19 17:01:09

标签: regex perl split

我的数据如下:

20110627 ABC DBE EFG
 217722 1425 1767 0.654504367955466 0.811585416264778 -0.157081048309312 

我试图以这样一种方式进行拆分,即将数值保存在一个单元格中,并将字符串保存在一个单元格中。

因此,我想要一个单元格中的“20110627”,另一个单元格中的“ABC DBE EFG”,另一个单元格中的“0.811585416264778”,另一个中的“-0.157081048309312”等。

我在Perl中使用正则表达式

进行以下拆分命令
my @Fld = split(/[\d+][\s][\w+]/, $_);

但这似乎没有做我想要的..有人可以告诉我使用哪个正则表达式?提前致谢

编辑:在vks建议之后,我改变了他的正则表达式以消除空格,考虑到字符串可能有逗号(,)或斜线(/)或短划线( - )但是然后是负号( - )似乎被视为数字中的单独标记:

(-?\d+(\.\d+)?)|([\/?,?\.?\-?a-zA-Z\/ ]+)

20110627 A B C
 217722 1425 1767 0.654504367955466 0.811585416264778 -0.157081048309312 
19950725 A C
 16458 63 91 0.38279256288735 0.552922590837283 -0.170130027949933 
19980323 G C I /DE/
20130516 A - E, INC.
 33019 398 197 1.205366607105 0.596626184923832 0.608740422181168 
20130516 A - E, INC.
 24094 134 137 0.556155059350876 0.56860629202291 -0.0124512326720345 
19960327 A F C /DE 38905 503 169 1.29289294435163 0.434391466392495 0.858501477959131 

预期产量: 20110627在一个令牌中 一个令牌中的B C. -0.170130027949933在一个令牌中 G C I / DE /在一个标记中 A - E,INC。在一个标记中..(当然所有其他标记应该在单独的标记中,换句话说,一个标记中的字符串和一个标记中的数字..我不能写出它们中的每一个但我认为它很简单)

第二次编辑:

布莱恩找到了正确的正则表达式:/( - ?~d +(?:。\ d +)?)|([/,。 - a-aA-Z] +(?:\ _ s + [/ - 。 zA-Z] +)*)/(见下文)。谢谢Brian!我现在有一个跟进问题:我正在使用以下代码将正则表达式拆分的结果写入Excel文件:

use warnings;
use strict;
use Spreadsheet::WriteExcel;
use Scalar::Util qw(looks_like_number);
use Spreadsheet::ParseExcel; 
use Spreadsheet::ParseExcel::SaveParser;
use Spreadsheet::ParseExcel::Workbook;

if (($#ARGV < 1) || ($#ARGV > 2)) {
    die("Usage: tab2xls tabfile.txt newfile.xls\n");
};
open (TABFILE, $ARGV[0]) or die "$ARGV[0]: $!";

my $workbook  = Spreadsheet::WriteExcel->new($ARGV[1]);
my $worksheet = $workbook->add_worksheet();
my $row = 0;
my $col = 0;

while (<TABFILE>) {
    chomp;
    # Split
    my @Fld = split(/(-?\d+(?:\.\d+)?)|([\/,.\-a-zA-Z]+(?:\s+[\/,.\-a-zA-Z]+)*)/, $_);

    $col = 0;
    foreach my $token (@Fld) {
            $worksheet->write($row, $col, $token);
            $col++;
        }
            $row++;
    }

问题是当我使用该代码时,我得到空单元格:

> "EMPTY CELL" "1000" "EMPTY CELL" "EMPTY CELL" "ABC DEG" "EMPTY CELL"
> "2500" "EMPTY CELL" "EMPTY CELL" "1500" "3500"

为什么我会得到这些空单元格?有什么办法可以避免吗?非常感谢

3 个答案:

答案 0 :(得分:2)

这是一个广泛的范围正则表达式,可以进行空白修剪 出于某种原因,Perl总是插入捕获 由于正则表达式基本上是\d\D,因此它匹配所有内容,
所以通过grep运行拆分结果会删除空元素。

我正在使用Perl 5.10,他们现在可能有一个noemptyelements标志。

正则表达式

 # \s*([-\d.]+|\D+)(?<!\s)\s*

 \s* 
 ( [-\d.]+ | \D+ )
 (?<! \s )
 \s* 

Perl

use strict;
use warnings;

$/ = undef;
my $data = <DATA>;

my @ary = grep { length($_) > 0 } split m/\s*([-\d.]+|\D+)(?<!\s)\s*/, $data;

for (@ary) {
   print "'$_'\n";
}

__DATA__

20110627 A B C
 217722 1425 1767 0.654504367955466 0.811585416264778 -0.157081048309312 
19950725 A C
 16458 63 91 0.38279256288735 0.552922590837283 -0.170130027949933 
19980323 G C I /DE/
20130516 A - E, INC.
 33019 398 197 1.205366607105 0.596626184923832 0.608740422181168 
20130516 A - E, INC.
 24094 134 137 0.556155059350876 0.56860629202291 -0.0124512326720345 
19960327 A F C /DE 38905 503 169 1.29289294435163 0.434391466392495 0.858501477959131 

输出

'20110627'
'A B C'
'217722'
'1425'
'1767'
'0.654504367955466'
'0.811585416264778'
'-0.157081048309312'
'19950725'
'A C'
'16458'
'63'
'91'
'0.38279256288735'
'0.552922590837283'
'-0.170130027949933'
'19980323'
'G C I /DE/'
'20130516'
'A - E, INC.'
'33019'
'398'
'197'
'1.205366607105'
'0.596626184923832'
'0.608740422181168'
'20130516'
'A - E, INC.'
'24094'
'134'
'137'
'0.556155059350876'
'0.56860629202291'
'-0.0124512326720345'
'19960327'
'A F C /DE'
'38905'
'503'
'169'
'1.29289294435163'
'0.434391466392495'
'0.858501477959131'

答案 1 :(得分:1)

(-?\d+(\.\d+)?)|([a-zA-Z ]+)

试试这个。看看demo.Grab捕获。删除空的。

http://regex101.com/r/lZ5mN8/35

答案 2 :(得分:1)

使用允许/,-等的修订后的要求,这里有一个正则表达式,它将捕获捕获组#1中的所有数字标记和捕获组中的alpha #2:

(-?\d+(?:\.\d+)?)|([\/,.\-a-zA-Z]+(?:\s+[\/,.\-a-zA-Z]+)*)

(参见regex101示例)

故障:

(-?\d+(?:\.\d+)?)(捕获组#1)匹配数字,可能带有负号和可能的小数位(在非捕获组中)

([\/,.\-a-zA-Z]+(?:\s+[\/,.\-a-zA-Z]+)*)(捕获组#2)将alpha字符串与可能的嵌入空格进行匹配