2014-09-01 27 views
0

我有一个输入字符串,我需要根据下面的要求进行拆分。如何使用数字后缀分割字符串?

输入字符串:

1. "string" 
    2. "String 12343534" 
    3. "String_12343534" 
    4. "Stringone Stringtwo 12343534" 
    5. "Stringone Stringtwo_12343534" 
    6. "string 23string 12343534" 
    7. "string 23string_12343534" 
    8. "string_23string 12343534" 
    9. "string_23string_12343534" 
10. "string 23string 4545stringthird 12343534" 
11. "string 23string 4545stringthird_12343534" 
12. "string_23string_stringthird_12343534" 
13. "string-23string-stringthird_12343534" 
14. "string_23string-stringthird_12343534" 

像这回事。和我必须分开分开字符串和数字分开

输出应该是这样的。

1. $str = "string" ; $num = ; 
    2. $str = "String" $num = "12343534"; 
    3. $str = "String" $num = "_12343534"; 
    4. $str = "Stringone Stringtwo" $num = "12343534"; 
    5. $str = "Stringone Stringtwo" $num = "_12343534"; 
    6. $str = "string 23string" $num = "12343534"; 
    7. $str = "string 23string" $num = "_12343534"; 
    8. $str = "string_23string" $num = "12343534"; 
    9. $str = "string_23string" $num = "_12343534"; 
    10. $str = "string 23string 4545stringthird" $num = "12343534"; 
    11. $str = "string 23string 4545stringthird" $num = "_12343534"; 
    12. $str = "string_23string_stringthird" $num = "_12343534"; 
    13. $str = "string-23string-stringthird" $num = "_12343534"; 
    14. $str = "string_23string-stringthird" $num = "_12343534"; 

任何人都可以帮助我吗?如何分割给定的字符串以获得上述输出?

回答

2

既然你想保留所有的东西,你必须拆分一个锚点。你可以使用这个向前看。拆分以下模式:

(?=_\d)|\s+(?=\d) 

所以:

my ($string, $numerical) = split /(?=_\d)|\s+(?=\d)/, $input; 

如果下划线的数字之前存在,它只是才将它分割,否则会各执任何空格后面跟着一个数字。这是正则表达式的翻译。

您还可以使用以下方式:

(?=_\d+$)|\s+(?=\d+$) 

这将确保没有什么迫使比赛进入到字符串末尾的数字后。如果最后有一个非数字字符,分割将不会发生。

但它更容易只是满足你需要的,而不是分裂IMO什么:

my ($string, $numerical) = $input =~ /^(.*?)\s*(_?\d+)$/; 

这是更具可读性和更好地传达你的意图。

+0

请问你能解释一下这个表达方式吗? – saravanakumar 2014-09-01 07:46:46

+0

@saravanakumar我试图添加一些解释,但这些正则表达式非常简单,所以我鼓励你阅读一些正则表达式教程 - 一旦你做了,你将能够立即写出这种表达式。 – 2014-09-01 08:47:29

+0

Thankyou @Lucas Trzesniewski。你能否给我一些regrex在线教程网站。 – saravanakumar 2014-09-01 17:46:05

0

你可以试试下面的代码,

my ($string, $numerical) = split/(?=\d+)|(?=_\d+)/, $str; 

(?=_\d+)称为正先行断言它接下来是下划线后面跟着一个或多个数字。如果这种情况是真的,那么正则表达式引擎会在_\d+之前设置匹配标记。根据这个零宽度匹配分裂会给你想要的结果。

+0

感谢avinash Raj,现在工作正常 – saravanakumar 2014-09-01 07:45:59

+0

@saravanakumar在这里接受任何答案,如果它更有帮助。 – 2014-09-01 08:16:34

0

既然你想split数值和字母字符之间的边界,你需要使用positive lookahead and lookbehind assertions

为决定在哪里有下划线的附加规范是不完全清楚,但是这是我最好的你的意图可能是解释:

use strict; 
use warnings; 

while (<DATA>) { 
    chomp; 
    my @fields = split m{(?<=[a-z])\s*(?=_*\d)|(?<=\d)\s*(?=_*[a-z])}i, $_; 

    use Data::Dump; 
    dd @fields; 
} 

__DATA__ 
string 123456 
string_45645645 
stringone stringtwo 23435345345 
string one string two_2335345345 

输出:

("string", 123456) 
("string", "_45645645") 
("stringone stringtwo", 23435345345) 
("string one string two", "_2335345345") 
1

我个人认为使用split的解决方案有点过于复杂,并且它们中的任何一个似乎都不能处理类似的字符串:

my $input = "code 4 you 12345678"; 

...我希望数字后缀是12345678,而不是“4”或“4你”。

我宁愿是这样的:

my ($string, $numerical) = $input =~ /^ (.+?) \s* (_?\d+) $/x; 

更新:我想我已经在上面解决方案涵盖了大部分的更新的例子:所有,但其中数字后缀是空的第一个例子。要覆盖第一个示例,当regexp根本无法匹配时,还需要将整个输入字符串设置为$string。事情是这样的:

my ($string, $numerical) = ($input =~ /^ (.+?) \s* (_?\d+) $/x) ? ($1, $2) : ($input); 
+0

我已经更新了需求(上面提到),我想根据这个更改正则表达式。我该如何改变? – saravanakumar 2014-09-01 13:42:17

+0

已更新,以涵盖您的额外要求。 – tobyink 2014-09-01 17:43:55