我有一个输入字符串,我需要根据下面的要求拆分它。
输入字符串:
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";
任何人都可以帮我这个吗?如何拆分给定的字符串以获得上述输出?
答案 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)