如何拆分带有数字后缀的字符串?

时间:2014-09-01 07:29:33

标签: regex string perl

我有一个输入字符串,我需要根据下面的要求拆分它。

输入字符串:

  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";

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

5 个答案:

答案 0 :(得分:2)

由于你想保留所有东西,你必须拆分一个锚点。您可以使用前瞻为例。按以下模式拆分:

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

所以:

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

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

您还可以使用以下内容:

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

通过强制匹配到字符串的末尾,这将确保数字后面没有任何内容。如果最后有一个非数字字符,那么分裂就不会发生。

但更容易匹配您需要的内容而不是拆分IMO:

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

这更具可读性,更能传达您的意图。

答案 1 :(得分: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);

答案 2 :(得分:0)

您可以尝试以下代码,

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

(?=_\d+)称为正向前瞻,断言后面是一个下划线后跟一个或多个数字。如果此条件为真,那么正则表达式引擎会将匹配标记设置在_\d+之前。根据此零宽度匹配进行拆分将为您提供所需的结果。

答案 3 :(得分: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")

答案 4 :(得分:0)

([a-zA-Z\s]*)(.*)$

这样可行。

参见演示。

http://regex101.com/r/rX0dM7/8