2013-11-27 3 views
0

В Perl я хочу разбить строку перед первой буквой (независимо от ее положения). Я не хочу, чтобы разделитель исчез.Perl, разделил строку перед первым буквенным символом

Например, если строка была 12345AB2345 я хочу разделить на первую букву A Я хочу две строки: 12345 и AB2345.

Я пробовал использовать код, как показано ниже, но он не разбивается правильно.

$string = "12345A2345" 
$substring = substr($string, 0, index($string, /[a-zA-Z]/); 
$remainder = substr($string, index($string, /[a-zA-Z]/); 

В строке может быть более одной буквы.

Я думаю, что моя проблема связана с тем, что substr не может использовать регулярные выражения.

+0

Do строки содержат только ASCII буквы и цифры? – Kenosis

+0

Да. Я не думаю, что мне нужно что-то другое, кроме цифр и английских букв. – Padawan

ответ

2

я бы, вероятно, использовать split здесь, так это то, что вы» re делать в конце концов. Ниже я дам вам выбор между 3 способами:

#!/usr/bin/perl 

use strict; 
use warnings; 

use Test::More; 

while(<DATA>) 
    { chomp; 
    my($string, $expected_substring, $expected_remainder)= split /\s+/; 

    { # method 1: split on letter, captured letter is added to the remainder 
     #   the 3rd arg to split is the LIMIT (see perldoc -f split) 
     my($substring, $letter, $remainder)= split /([a-zA-Z])/, $string, 2; 
     $remainder= $letter . $remainder if $letter; 

     is($substring, $expected_substring, "method 1, substring, s: '$string'"); 
     is($remainder, $expected_remainder, "method 1, remainder, s: '$string'"); 
    } 

    { # method 2: add space before letter, split on space 
     my $string_copy= $string;   # or $string would be modified 
     $string_copy=~ s/([a-zA-Z])/ $1/; 
     my($substring, $remainder)= split//, $string_copy, 2; 

     is($substring, $expected_substring, "method 2, substring, s: '$string'"); 
     is($remainder, $expected_remainder, "method 2, remainder, s: '$string'"); 
    } 

    { # method 3: method 2 shortened using s//r (perl 5.14 and above) 
     my($substring, $remainder)= split//, $string=~ s/([a-zA-Z])/ $1/r, 2; 

     is($substring, $expected_substring, "method 3, substring, s: '$string'"); 
     is($remainder, $expected_remainder, "method 3, remainder, s: '$string'"); 
    } 
    } 

done_testing(); 

# test data, string, substring and remainder are on one line, space separated 
__DATA__ 
12345A678 12345 A678 
12345AB678 12345 AB678 
12345A67B8 12345 A67B8 
12345678 12345678 
0

Попробуйте,

my ($substring,$remainder) = $string =~ /^([^a-zA-Z]*)([a-zA-Z].*)$/ ; 

Если вам нужно обработать случай, где нет ни одного письма, то вы могли бы сделать:

my ($substring,$remainder) = $string =~ /^([^a-zA-Z]*)([a-zA-Z].*)?$/ ; 
+0

Прошу прощения за отсутствие ясности. Я отредактировал вопрос, чтобы лучше объяснить себя. Я думаю, что код будет работать только в том случае, если в строке есть одна буква ??? (Это все, начиная со второй буквы, будет потеряно?) – Padawan

+1

'[a-zA-Z]' соответствует одной букве. то '. *' соответствует остальной части строки. – woolstar

+1

Это хорошо, но если в строке нет букв, тогда этот шаблон не сможет ничего сопоставить. Что-то вроде этого может быть ближе: 'my ($ substring, $ остаток) = $ string = ~/^ ([^ [: alpha:]] *) (. *) $ /;' –

3

И еще один способ:

my $string = "12345A2345"; 
my ($substring, $remainder) = split /(?=[a-z])/i, $string, 2; 
Смежные вопросы