2013-08-13 4 views
0

Скажем, у меня есть линия lead=george wife=jane "his boy"=elroy. Я хочу расстаться с пространством, но это не включает часть «его мальчика». Я должен считаться одним.Как пропустить расщепление для некоторой части линии

С нормальным расколом он также раскалывает «своего мальчика» как принятие «своего» как одного, так и «мальчика» в качестве второй части. Как избежать этого

После этого я попытался

Просто пришел, чтобы узнать, что это будет работать

use strict; use warnings; 

my $string = q(hi my name is 'john doe'); 
my @parts = $string =~ /'.*?'|\S+/g; 
print map { "$_\n" } @parts; 

Но это не выглядит хорошо. Любая другая простая вещь с расщеплением?

ответ

2

sub split_space { 
    my ($text) = @_; 

    while (
    $text =~ m/ 
     (    # group ($1) 
     \"([^\"]+)\" # first try find something in quotes ($2) 
     | 
     (\S+?)  # else minimal non-whitespace run ($3) 
    ) 
     = 
     (\S+)   # then maximum non-whitespace run ($4) 
    /xg 
) { 
    my $key = defined($2) ? $2 : $3; 
    my $value = $4; 

    print("key=$key; value=$value\n"); 
    } 
} 

split_space('lead=george wife=jane "his boy"=elroy'); 

Выходы:

key=lead; value=george 
key=wife; value=jane 
key=his boy; value=elroy 
+1

+1, приятно видеть комментировал не регулярные выражения –

+0

Нет необходимости, чтобы избежать двойных кавычек внутри регулярного выражения. Кроме того, это не позволяет избежать кавычек внутри строк с кавычками. – TLP

+0

@TLP действительные комментарии. Благодарю. –

5

Вы могли бы использовать для этого Text::ParseWords

use Text::ParseWords; 

$list = "lead=george wife=jane \"his boy\"=elroy"; 

@words = quotewords('\s+', 0, $list); 
    $i = 0; 
    foreach (@words) { 
     print "$i: <$_>\n"; 
     $i++; 
    } 

поток вывода:

0: <lead=george> 
1: <wife=jane> 
2: <his boy=elroy> 
+0

+1 для строк с текстом 'Text :: ParseWords'. – TLP

0

PP опубликовал хорошее решение. Но просто чтобы убедиться, что это круто другой способ сделать это, приходит мое решение:

my $string = q~lead=george wife=jane "his boy"=elroy~; 

my @split = split/(?=")/,$string; 
my @split2; 
foreach my $sp (@split) { 
    if ($sp !~ /"/) { 
    push @split2, $_ foreach split//, $sp; 
    } else { 
    push @split2,$sp; 
    } 
} 
use Data::Dumper; 
print Dumper @split2; 

Выход:

$VAR1 = 'lead=george'; 
$VAR2 = 'wife=jane'; 
$VAR3 = '"his boy"=elroy'; 

Я использую LOOKAHEAD здесь для расщепления на первых частей, которые ключи находятся внутри котировок " ". После этого я просматриваю полный массив и разбиваю все остальные части, которые являются нормальными key=values.

0

Вы можете получить требуемый результат, используя одно регулярное выражение, которое извлекает ключи и значения и помещает результат в хэш-таблицу.

(\ w + | "[\ w] +") будет соответствовать как одному, так и нескольким словам на стороне ключа. Регулярное выражение захватывает только ключ и значение, поэтому результатом операции совпадения будет список со следующим содержимым: ключ № 1, значение № 1, ключ № 2, значение № 2 и т. Д.

хеш автоматически запускается с соответствующими ключами и значениями, когда ему присваивается результат сопоставления.

здесь код

my $str = 'lead=george wife=jane "hello boy"=bye hello=world'; 

my %hash = ($str =~ m/(?:(\w+|"[\w ]+")=(\w+)(?:\s|$))/g); 

## outputs the hash content 
foreach $key (keys %hash) { 
    print "$key => $hash{$key}\n"; 
} 

и вот вывод этого сценария

lead => george 
wife => jane 
hello => world 
"hello boy" => bye 
Смежные вопросы